Descending ranges in Ruby

H

Harry Spier

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
 
P

pat eyler

[Note: parts of this message were removed to make it a legal post.]

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


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
 
H

Harry Spier

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
 
V

Victor D.

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.
 
R

Robert Klemme

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?". =A0For 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 #<=3D>, example:

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

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

Kind regards

robert

--=20
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,142
Latest member
DewittMill
Top