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