Code block passed to each works with brackets but not with 'do'-'end' (ruby)
I recently started learning ruby, and I understood that you coud use code blocks with both of these syntaxes. But I just found a case which I dont understand:
#my_hash is a hash in which the keys are strings and the values arrays, but dont think about the specifics fo the code
#if I run my code like this, it works perfectly
my_hash.each do |art|
puts mystring.gsub(art[0]).each {
art[1][rand(art[1].length) -1]
}
end
#but if I use this, it prints "Enumerator"
my_hash.each do |art|
puts mystring.gsub(art[0]).each do
art[1][rand(art[1].length) -1]
end
end
Is it because you cant nest do-end pairs? I am using 1.9
puts mystring.gsub(art[0]).each do
art[1][rand(art[1].length) -1]
end
Here you called puts
without parens, the do ... end
refers to the puts
method, that does nothing with a block and prints mystring.gsub(art[0]).each
(with is a Enumerator
).
The { ... }
is called with the nearest method. Becomes ugly, but you can do it with do ... end
:
puts(mystring.gsub(art[0]).each do
art[1][rand(art[1].length) -1]
end)
Or, better, put the result in a variable and print the variable:
var = mystring.gsub(art[0]).each do
art[1][rand(art[1].length) -1]
end
puts var
Anyway, the each
don't changes the object, it just iterate and returns the object itself. You may be wanting the map
method, test it.
Expanding on Scott's reply, and quoting Jim Weirich:
The difference is where in the operator precedence table they fall. { } binds tighter than do/end. For example:
f g { }
is parsed as f(g { }), where the braces belong to the method g. On the other hand,
f g do end
is parsed as f(g) do end, where the braces belong to the method f. It only matters when you omit parenthesis and create ambiguities.