Looping differences in Ruby using Range vs. Times
This information can be easily obtained by inspecting the documentation.
Array#each
has a signature of array.each {|item| block } → array
, so we can see that the return value of foo.each { ... }
is foo
.
Likewise, Int#upto
has a signature of int.upto(limit) {|i| block } => int
, so that x.upto(y) { ... }
will always return x
.
Then we can also see that 2.times { ... }
will return 2 because of Integer#times
's signature.
I'm having trouble finding the right documentation, but for x in y...
gets translated to y.each do |x| ...
, so that's why your for-in loop returns the same thing as your .each
loop.
Anyway, depending on the return values of these looping constructs is... a strange approach. I don't think this happens much (at all?) in idiomatic Ruby code.
If I understood you correctly, you're asking why n.times
is the only method which iterates upto, but not including n
. In that case:
For ranges it's simple: x..y
defines a range from x to y inclusive and x...y
defines a range from x to y exclusive. So if you want the same behavior as times use 0...n
.
For x.upto(y)
there is only one version which will iterate upto and including y
. This is simply how upto is defined and documented to work.
It is also quite clear why n.times
does not include n: if it iterated from 0 to n (inclusive), it would yield n+1
times. But since the method is called n.times
it should clearly only yield n times.