This code:
puts 1.times { puts 2.times { puts 3.times { puts 4 } } }
Outputs this:
4 4 4 3 4 4 4 3 2 1
I would expect Ruby to output the return value of the times method, but it doesn't seem to do that. It prints out the number that times is being called on. What is happening?
To multiply two numbers using the box method, make a table with the place values of the first factor along the top and the place values of the second factor down the left. Multiply the place values and enter their products in the table. Simplify the table. Sum each row of the table.
You've got a (quasi) loop within a loop within a loop so Ruby's doing exactly what you're asking of it. The way these loops are evaluated is, generally speaking, from the inside out.
The return value from times is the number given in the first place, so 3.times returns 3.
With all that in mind you can interpret what's happening as this:
4 # First iteration of 3.times { puts 4 }
4
4
3 # Return value of 3.times displayed
4 # Second iteration of 3.times { puts 4 }
4
4
3 # Return value of 3.times displayed
2 # Return value of 2.times displayed
1 # Return value of 1.times displayed
Now when I see code like puts 3.times that's usually a mistake, same goes for puts array.each ... where someone probably means .map.
I don't really get that output either, so let's dissect it, starting with the innermost expression:
puts 4
# 4 <- this should denote output
#=> nil <- this should denote return value
It prints 4 and returns nil (puts always returns nil).
Wrapping it in 3.times { ... } prints 4 3 times:
3.times { puts 4 }
# 4
# 4
# 4
#=> 3
But instead of returning nil, it returns 3. This is because times always returns the receiver (i.e. the integer you call times on).
Now let's add another puts:
puts 3.times { puts 4 }
# 4
# 4
# 4
# 3
#=> nil
Same as above, but also prints the result of 3.times { ... }, i.e. 3.
Wrapping everything in 2.times { ... } duplicates the above output:
2.times { puts 3.times { puts 4 } }
# 4
# 4
# 4
# 3
# 4
# 4
# 4
# 3
#=> 2
It also returns 2 instead of nil because of 2.times { ... }.
Adding puts prints that 2:
puts 2.times { puts 3.times { puts 4 } }
# 4
# 4
# 4
# 3
# 4
# 4
# 4
# 3
# 2
#=> nil
Wrapping this in 1.times { ... } produces the same output, but changes the result from nil to 1:
1.times { puts 2.times { puts 3.times { puts 4 } } }
# 4
# 4
# 4
# 3
# 4
# 4
# 4
# 3
# 2
#=> 1
Adding the last puts prints that 1:
puts 1.times { puts 2.times { puts 3.times { puts 4 } } }
# 4
# 4
# 4
# 3
# 4
# 4
# 4
# 3
# 2
# 1
#=> nil
I guess I'd expect Ruby to output the return value of the
timesmethod, but it doesn't seem to do that. It prints out the number thattimesis being called on.
That is the return value of the times method:
times {|i| block }→self
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