What is it called when you pass a block to a method in this way: .map(&:capitalize)
?
Is it just syntactic sugar? Shorthand? Can you do anything else with it?
What is it called when you pass a block to a method in this way: .map(&:capitalize)
?
Is it just syntactic sugar? Shorthand? Can you do anything else with it?
Every method in Ruby has a special "block" slot that isn't a normal argument. This is because passing precisely one block to a method is the most common use case and Ruby optimizes it¹. The &
symbol is used to denote the passing of something specifically inside that slot.
def with_regular_argument(block)
block.call
end
def with_block_argument(&block)
block.call
end
with_regular_argument lambda { puts 'regular' } # regular
with_block_argument { puts 'block argument' } # block argument
The symbol can also be used when calling methods. That way, you can pass any object as the block, and to_proc
will be called on it in order to coerce it to a Proc
.
def to_proc
proc { puts 'the main object was converted to a Proc!' }
end
with_block_argument &self # the main object was converted to a Proc!
Note that the coercion would not have been performed had you invoked with_regular_argument
:
begin
with_regular_argument self
rescue => error
puts error.message # undefined method `call' for main:Object
end
The Symbol
class implements to_proc
. It basically works like this:
class Symbol
def to_proc
proc { |receiver| receiver.send self }
end
end
So, how does the following line work?
enumerable.map &:to_s
:to_s
in the special block slot. This is denoted by the &
.&
calls to_proc
on the symbol.to_proc
returns a Proc
that sends :to_s
to the first argument.Proc
is then passed to the map
method in the special block slot.It is pretty much equivalent to:
enumerable.map { |receiver| receiver.send :to_s }
¹ Yehuda Katz. Ruby is NOT a Callable Oriented Language (It’s Object Oriented). Blog post.