I just ran into an issue where the value returned by a function is different depending on whether or not I call puts on that result. I'm wondering if this is to be expected, or some sort of parser error.
This only occurs if the block passed to the function uses the do...end
syntax, not the inline {...}
syntax. Here's an example:
arr = ["a", "b", "c"]
puts i = arr.index { |x| == "b" }
#=> 1
as expected, but this does not work as I'd expect:
arr = ["a", "b", "c"]
puts i = arr.index do |x|
x == "b"
end
#=> #<Enumerator:0xSomeId>
Though it works fine if I do:
arr = ["a", "b", "c"]
i = arr.index do |x|
x == "b"
end
puts i
#=> 1
It looks like it's interpreted as if it were passed no block at all (returning the enumerator is the expected behavior of calling arr.index
with block). Is this normal? Is this behavior explained/documented anywhere?
do...end
blocks associate with the leftmost method while {...}
blocks associate with the rightmost, due to precedence. In your second example, the block is being associated with puts
, which does nothing with it.
It seems like weird behavior in this case, but it's this feature of do...end
blocks that give a lot of Ruby DSL's their clean, readable syntax.
{ ... }
binds more tightly than do ... end
, so your do ... end
block ends up attached to IO#puts
(which ignores it) and not Array#index
.
If you put then parens into the puts() call
you can see:
puts(i = arr.index do |x| x == 'b' end)
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