Disclaimer: This post is purely educational. nums.each {|n| puts n} is really the only reasonable thing to write in a real project.
nums.map(&:to_s)The existing short form works very simply. & calls to_proc on the symbol, and to_proc on a symbol is defined like this.
class Symbol
def to_proc
Proc.new { |*args| args.shift.__send__(self, *args) }
end
end
Since this proc will start acting like a regular block that is passed into map, the *args in this case is really each element we're iterating through. We take the first of args (since * turns arguments into an array), and send self to it, self being the actual symbol, such as :to_s. Remaining arguments are passed in. So it's like saying nums.map{ |*args| args.shift.__send__(:to_s, *args) }.
nums.each(&:puts)We could easily re-implement to_proc to act differently. Here's a quick example.
class Symbol
def to_proc
Proc.new { |*args| __send__(self, *args) }
end
end
(1..10).each(&:print) # => 12345678910
Here instead of sending symbol name as a message to the element, we are just calling symbol as a method on the current context, and simply passing the iterated element as an argument to it.
So it's more like saying (1..10).each{|*args| __send__(:print, *args)}.
nums.each(&method(:puts))That said, as nash pointed out you could call nums.each(&method(:puts)). What happens there is that you get an object that represents method puts using ruby's method method. So then & calls .to_proc on the method object, turning it into proc, which itself s