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,8,10] p a.map do |n| n*2 end #=> [1,2,3,4,5]
From Programming Ruby: Braces have a high precedence; do has a low precedence. If the method invocation has parameters that are not enclosed in parentheses, the brace form of a block will bind to the last parameter, not to the overall invocation. The do form will bind to the invocation.
There are two ways of defining a block in Ruby: The first is using the do.. end keyword, the other is using a pair of curly braces. Do.. end block is mainly used when defining a block of code that spans multiple lines, while curly braces {} are used when defining a block of code that spans a single line.
The square brackets [ ] are used to initialize arrays. The documentation for initializer case of [ ] is in ri Array::[] The curly brackets { } are used to initialize hashes.
What is a ruby block? A ruby block is one or more lines of code that you put inside the do and end keywords (or { and } for inline blocks). It allows you to group code into a standalone unit that you can use as a method argument.
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 {
.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With