tags:

views:

137

answers:

2

I'm trying to solve a Project Euler problem using Ruby, I used 4 different looping methods, the for-loop, times, range and upto method, however the times method only produces the expected answer, while the for-loop, range and upto method does not. I'm assuming that they are somewhat the same, but I found out it's not. Can someone please explain the differences between these methods?

Here's the looping structure I used

# for-loop method
for n in 0..1
  puts n
end

0
1
=> 0..1

# times method
2.times do |n|
  puts n
end

0
1
=> 2

# range method
(0..1).each do |n|
  puts n
end

0
1
=> 0..1

# upto method
0.upto(1) do |n|
  puts n
end

0
1
=> 0
+4  A: 

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.

Mark Rushakoff
It doesn't sound to me like he's asking about the return value.
sepp2k
@sepp2k: I saw that the *output* of each statement was `0 1`, while the return values as indicated by `=>` had 3 different values. The question could have been worded more clearly, in any case.
Mark Rushakoff
Hm, you're probably right.
sepp2k
A: 

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.

sepp2k