Why does this map expression produce different results depending on whether I use braces or do/end?
a = [1,2,3,4,5]
p a.map { |n|
n*2
}
#=> [2,4,6
That has to do with the difference in associativity of the {
character and the do
keyword.
In the first case, the block is interpreted as a block argument to the map
function. The result of the map function is the argument to the p
function.
In the second case, the block is interpreted as a block argument to the p
function, while the a.map
is interpreted as the first argument to the p
function. Since a.map
evaluates to a
, this prints the original array. The block is effectively ignored in this case.
With the do/end
syntax you are passing the block to p
as a second argument, rather than to the map. You get the same result with:
p a.map
The block is ignored by p
as it does not produce anything on inspect
.
That's because the second line is interpreted as:
p(a.map) do ... end
instead of:
p(a.map do ... end)
The grammar is ambiguous in this case and do
doesn't seem to bind as strongly as {
.