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
times
method, but it doesn't seem to do that. It prints out the number thattimes
is 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