views:

794

answers:

3

In Ruby (actually only in Rails, apparently), I know that if I do:

some_objects.each(&:foo)

It's the same as

some_objects.each { |obj| obj.foo }

That is -- &foo creates the block { |obj| obj.foo }, turns it into a Proc, and passes it to each. Why does this work? Is it just a Ruby special case, or is there reason why this works as it does?

+1  A: 

Just found the answer after a bit of searching. This article by Jarkko Laine does a great job explaining it: http://jlaine.net/2008/5/8/amp-lified

Basically this is not a Ruby shortcut, but a clever hack done by Rails. Rails adds a to_proc method to Symbol. The ampersand calls to_proc on the symbol to turn into a proc, and the handy to_proc method is used:

class Symbol
  def to_proc
    lambda {|i| i.send(self)}
  end
end
Allan Grant
+13  A: 

Your question is wrong, so to speak. What's happening here isn't "ampersand and colon", it's "ampersand and object". The colon in this case is for the symbol. So, there's & and there's :foo.

The & calls to_proc on the object, and passes it as a block to the method. In Rails, to_proc is implemented on Symbol, so that these two calls are equivalent:

something {|i| i.foo }
something(&:foo)

Also, to_proc on Symbol is implemented in Ruby 1.8.7 and 1.9, so it is in fact a "ruby thing".

So, to sum up: & calls to_proc on the object and passes it as a block to the method, and Rails implements to_proc on Symbol.

August Lilleaas
More precisely: the ampersand unpacks the `Proc` object so that it gets passed as if it was a literal block. Only if the object is not *already* a `Proc` object, does it call `to_proc`.
Jörg W Mittag
Symbol#to_proc is only native in Ruby > 1.9
Steve Graham
August Lilleaas
you're right. it's not in http://ruby-doc.org/core/classes/Symbol.html for some weird reason though?! :S
Steve Graham
http://ruby-doc.org/core/ is for 1.8.7, http://ruby-doc.org/core-1.8.7 / is the 1.8.7 equivalent. Here's the entry: http://ruby-doc.org/core-1.8.7/classes/Symbol.html#M000086
August Lilleaas
Thanks, that makes sense. Good to know that it's in Ruby 1.8.7 and 1.9.
Allan Grant
thanks august. do you know what version of ruby the default docs cover? i.e. /core not /core-1.8.7, /core-1.9. i always thought it was the latest release of 1.8? the way it is is not very helpful!
Steve Graham
It is explained on http://www.ruby-doc.org/. /core is 1.8.6, then there's /core-1.8.7/ and /ruby-1-9/ (yay for no convention).
August Lilleaas
+4  A: 

I actually blogged about this very thing last week:

http://swaggadocio.com/post/287689063

Steve Graham
Thanks. Your post does a great job explaining the exact Rails Symbol#to_proc implementation. The passing of arguments was a new point for me that I haven't seen mentioned elsewhere.
Allan Grant