Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why the Ruby each iterator goes first in the execution?

I've came across a weird thing doing simple tasks in Ruby. I just want to iterate the alphabet with the each method but the iteration goes first in the execution:

alfawit = ("a".."z")
puts "That's an alphabet: \n\n #{ alfawit.each { |litera| puts litera } } "

and this code results in this: (abbreviated)

a
b
c
⋮
x
y
z
That's an alphabet: 

 a..z 

Any ideas why it works like this or what supposedly I did wrong?

Thanks in advance.

like image 936
Michalko Avatar asked Feb 21 '17 09:02

Michalko


Video Answer


2 Answers

Because your each call is interpolated in your string literal that's executed before the fixed string. Also, each returns an Enumerable, in fact you print even that. Try this one

alfawit = ("a".."z")
puts "That's an alphabet: \n\n"
alfawit.each { |litera| puts litera } 

or

puts "That's an alphabet: \n\n"
("a".."z").each { |litera| puts litera } 

you can use interpolation if you want but in this way

alfawit = ("a".."z")
puts "That's an alphabet: \n\n#{alfawit.to_a.join("\n")}"
like image 76
Ursus Avatar answered Oct 23 '22 07:10

Ursus


You can easily see what's going on if you extract the interpolation part into a variable:

alfawit = ("a".."z")
foo = alfawit.each { |litera| puts litera }
puts "That's an alphabet: \n\n #{ foo } "

The second line is causing the trouble: each invokes the block for each element of the range and then returns the receiver, so that foo becomes alfawit.

Here's another way to get the desired result:

alfawit = "a".."z"
puts "That's an alphabet:", alfawit.to_a

puts outputs each argument on a new line, but for array arguments, it outputs each element on a new line. Result:

That's an alphabet:
a
b
c
⋮
x
y
z

Likewise, you can turn the range into an argument list via *:

alfawit = "a".."z"
puts "That's an alphabet:", *alfawit

That's equivalent to:

puts "That's an alphabet:", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"
like image 26
Stefan Avatar answered Oct 23 '22 07:10

Stefan