Descending ranges in Ruby

Dear list members,

(5…1).to_a #returns []
(1…5).to_a #returns [1,2,3,4,5]
(5…1).each{|x| puts x} #prints (-5…-1)
(1…5).each{|x| puts x} #prints
1
2
3
4
5

I don’t get an error message when I declare a descending Range or when I
apply an iterator method to it, but I’m not able to iterate over a
descending Range the same way I can an ascending Range. Can someone
explain what the rationale is behind that language restriction?

Thanks,
Harry

5.downto(1) { |i| puts i }
5
4
3
2
1

Thanks for this work-around but my question was not so much how to get
around this restriction but rather “why I’m restricted from iterating
over a descending range if descending Ranges are legal?”. For example a
Range returned by a function in my program that I may not know whether
it is ascending or descending?

Harry

AFAIK, ruby simply considers values like (5…1) as empty range.
Iterating over it has no sense. You can iterate over ascending range in
reverse order using Enumerable#reverse_each method, for example.

On Fri, Nov 19, 2010 at 5:49 AM, Harry S. [email protected]
wrote:

Thanks for this work-around but my question was not so much how to get
around this restriction but rather “why I’m restricted from iterating
over a descending range if descending Ranges are legal?”. For example a
Range returned by a function in my program that I may not know whether
it is ascending or descending?

IIRC a Range finds the next value via #succ. And Fixnum#succ always
yields the next higher number. If you want to use a Range you must
use a type which reverses #succ and #<=>, example:

irb(main):001:0> RFN = Struct.new :value do
irb(main):002:1* def <=>(o) o.value <=> value end
irb(main):003:1> def succ; self.class.new(value - 1) end
irb(main):004:1> end
=> RFN
irb(main):005:0> (RFN.new(5) … RFN.new(1)).to_a
=> [#, #, #, #, #]

I’d rather stick with the other approaches presented or use
Array#reverse.

Kind regards

robert

On Nov 19, 5:01am, Harry S. [email protected] wrote:

Dear list members,

(5…1).to_a #returns []
(1…5).to_a #returns [1,2,3,4,5]

(1…5).to_a.reverse
=> [5, 4, 3, 2, 1]

– Maurice