Adding Array#to_proc to Ruby

Tagged:

Here's a neat Ruby trick for fans of Symbol#to_proc.

This magical method, introduced by both Rails and Ruby 1.9, lets you do things like this:

> %w(1 2 3 4 5).map &:to_i
=> [1, 2, 3, 4, 5]

And that proc can, of course, take multiple parameters:

[1,2,3,4].zip([2,3,4,5])
=> [[1, 2], [2, 3], [3, 4], [4, 5]]> [1,2,3,4].zip([2,3,4,5]).map &:sum
=> [3, 5, 7, 9]

However, if you want to "close" a value into the proc, you're out of luck, so you have to define a block old-school-style:

> %w(kung ruby bar).map { |e| e + "-fu" }
=> ["kung-fu", "ruby-fu", "bar-fu"]

But check out the following little hack:

class Array
  def to_proc
    lambda { |target| target.send(*self) }
  end
end

Now look what you can do:

> %w(kung ruby bar).map &[:+, "-fu"]
=> ["kung-fu", "ruby-fu", "bar-fu"]

What do you think? Handy? Disgusting? Leave a comment to let me know!

Update: apparently others have had similar ideas, but with different semantics. So perhaps this trick is a little too opaque...

Liked this? Why not subscribe to my news feed to get more of the same in future.

Hi Steve. Array#to_proc is a clever trick. Too clever in my opinion. As much as I like Symbol#to_proc (shorter code and spares from having to find a name for the block variable), I think that as soon as more than one method is to be called inside the block, it's time to revert to the normal block syntax; in your example: %w(kung ruby bar).map { |word| word + "-fu" }.

Yes, Roman, I'm inclined to agree; I've never put this into a "real" codebase, and this was an intellectual exercise to see how I'd want it to work. The fact that there are 3 very different implementations of Array#to_proc is a clear sign that there's no good "right" way.

Syndicate content