This question already has an answer here:
Why will (1..5).each
iterate over 1,2,3,4,5
, but (5..1)
will not? It returns the Range instead.
1.9.2p290 :007 > (1..5).each do |i| puts i end
1
2
3
4
5
=> 1..5
1.9.2p290 :008 > (5..1).each do |i| puts i end
=> 5..1
Ranges use
<=>
to determine if an iteration is over;5 <=> 1 == 1
(greater-than), so it's done before it starts. Even if they didn't, ranges iterate usingsucc
;5.succ
is6
, still out of luck. A range'sstep
cannot be negative, so that won't work either.It returns the range because
each
returns what it was called on. Usedownto
if it's the functionality itself you're looking for, otherwise the above answers your actual question regarding "why".The easiest way to do that is use downto
This doesn't even really have anything to do with Ruby, it's just simple basic math: the range which starts with
5
and ends with1
is empty. There is nothing to iterate over.Because Ruby only does what it's told, not what you mean.
It can't tell whether you want to go in reverse (ie 5, 4, 3, 2, 1), or whether you really only want the numbers starting from 5 that are less than or equal to 1. It's theoretically possible that someone may want the latter, and because Ruby can't tell what you really want, it'll go with the latter.
You can easily extend the Range class, in particular the each method, to make it compatible with both ascending and descending ranges:
Then, the following code will perform just as you'd expect: