Why will a Range not work when descending? [duplicate]
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 using succ
; 5.succ
is 6
, still out of luck. A range's step
cannot be negative, so that won't work either.
It returns the range because each
returns what it was called on. Use downto
if it's the functionality itself you're looking for, otherwise the above answers your actual question regarding "why".
You can easily extend the Range class, in particular the each method, to make it compatible with both ascending and descending ranges:
class Range def each if self.first < self.last self.to_s=~(/\.\.\./) ? last = self.last-1 : last = self.last self.first.upto(last) { |i| yield i} else self.to_s=~(/\.\.\./) ? last = self.last+1 : last = self.last self.first.downto(last) { |i| yield i } end endend
Then, the following code will perform just as you'd expect:
(0..10).each { |i| puts i}(0...10).each { |i| puts i}(10..0).each { |i| puts i}(10...0).each { |i| puts i}