Block Argument
The &
symbol is used to denote a block argument in a method definition.
def each_with_index(&block)
...
end
Fetch as an example
Let's look at a practical example by reimplementing part of #fetch
↗.
The #fetch
method will try to grab a value from a hash using the key. We can optionally include a block argument which will be called on a miss.
h = { "a" => 100, "b" => 200 }
h.fetch("a") #=> 100
h.fetch("z", "go fish") #=> "go fish"
h.fetch("z") { |el| "go fish, #{el}"} #=> "go fish, z"
A simplified version of #fetch
might look like this:
def fetch(key, default = nil, &block)
if has_key?(key)
self[key]
elsif block_given?
yield key
elsif default
default
else
raise KeyError, "key not found: #{key.inspect}"
end
end
If we have the block argument (block_given?
) and the key isn't present (self.has_key?
), we call the block with the key.
Forwarding a block argument
Here is another example where you can see the block argument alongside the positional and keyword arguments.
def forwarding_method(*x, **y, &block)
target_method(*x, **y, &block)
end
Note: if you're doing something like the above block, you may be interested in the Argument Forwarding syntax.