# Reverse-range alternatives?

**URL:** https://rubytalk.org/t/reverse-range-alternatives/38103
**Category:** ruby-talk
**Created:** [4 June 2007 20:51 UTC](https://rubytalk.org/t/reverse-range-alternatives/38103 "2007-06-04T20:51:32Z")
**Posts on this page:** 11
**Page:** 1

<div class="post-metadata">

### Author: ![Kenneth\_McDonald](https://avatars.discourse-cdn.com/v4/letter/k/dc4da7/32.png) [@Kenneth\_McDonald](https://rubytalk.org/u/Kenneth_McDonald)
#### Post date: [4 June 2007 20:51 UTC](https://rubytalk.org/t/reverse-range-alternatives/38103/1 "2007-06-04T20:51:32Z")

</div>

Since a reverse range (eg. 4...1) is functionally almost the same as an empty range, is there an alternative in the standard library, where .each would actually iterate over the elements from first to last, in this case 4, 3, 2?

Thanks,  
Ken

---

<div class="post-metadata">

### Author: ![Frew\_Schmidt](https://avatars.discourse-cdn.com/v4/letter/f/f05b48/32.png) [@Frew\_Schmidt](https://rubytalk.org/u/Frew_Schmidt)
#### Post date: [4 June 2007 21:23 UTC](https://rubytalk.org/t/reverse-range-alternatives/38103/2 "2007-06-04T21:23:44Z")

</div>

You could do 4.downto(2) { |i| ... }

> **···**
>
> On 6/4/07, Kenneth McDonald \<kenneth.m.mcdonald@sbcglobal.net\> wrote:
> 
> > Since a reverse range (eg. 4...1) is functionally almost the same as an  
> > empty range, is there an alternative in the standard library, where  
> > .each would actually iterate over the elements from first to last, in  
> > this case 4, 3, 2?
> > 
> > Thanks,  
> > Ken
> 
> --  
> -fREW

---

<div class="post-metadata">

### Author: ![Robert\_K1](https://yyz1.discourse-cdn.com/flex029/user_avatar/rubytalk.org/robert_k1/32/1830_2.png) [@Robert\_K1](https://rubytalk.org/u/Robert_K1)
#### Post date: [5 June 2007 00:02 UTC](https://rubytalk.org/t/reverse-range-alternatives/38103/3 "2007-06-05T00:02:39Z")

</div>

$ ruby -e '4.downto 1 do |i| p i end'  
4  
3  
2  
1

robert@fussel ~  
$ ruby -e '4.step 1, -1 do |i| p i end'  
4  
3  
2  
1

Kind regards

&nbsp;&nbsp;robert

> **···**
>
> On 04.06.2007 22:51, Kenneth McDonald wrote:
> 
> > Since a reverse range (eg. 4...1) is functionally almost the same as an empty range, is there an alternative in the standard library, where each would actually iterate over the elements from first to last, in this case 4, 3, 2?

---

<div class="post-metadata">

### Author: ![\_Pena\_Botp1](https://avatars.discourse-cdn.com/v4/letter/_/94ad74/32.png) [@\_Pena\_Botp1](https://rubytalk.org/u/_Pena_Botp1)
#### Post date: [5 June 2007 01:32 UTC](https://rubytalk.org/t/reverse-range-alternatives/38103/4 "2007-06-05T01:32:02Z")

</div>

# Since a reverse range (eg. 4...1) is functionally almost the  
# same as an  
# empty range, is there an alternative in the standard library, where  
# .each would actually iterate over the elements from first to last, in  
# this case 4, 3, 2?

assumming we're all talking about range.

irb(main):014:0\> x  
=\> 1..4  
irb(main):015:0\> x.class  
=\> Range  
irb(main):016:0\> x.last  
=\> 4  
irb(main):017:0\> x.first  
=\> 1  
irb(main):018:0\> x.last.downto x.first do |e|  
irb(main):019:1\* p e  
irb(main):020:1\> end  
4  
3  
2  
1  
=\> 4

but i really hope something of a bidirectional range, ie, (4..1).to\_a == [4,3,2,1] and (4..1)==(1..4).reverse, and then (4..1).each{|x| p x =\>4,3,2,1

right now (4..1) is useless, but it does not \_err..

kind regards -botp

> **···**
>
> From: Kenneth McDonald [[mailto:kenneth.m.mcdonald@sbcglobal.net](mailto:kenneth.m.mcdonald@sbcglobal.net)] :

---

<div class="post-metadata">

### Author: ![Daniel\_DeLorme](https://avatars.discourse-cdn.com/v4/letter/d/9d8465/32.png) [@Daniel\_DeLorme](https://rubytalk.org/u/Daniel_DeLorme)
#### Post date: [5 June 2007 04:47 UTC](https://rubytalk.org/t/reverse-range-alternatives/38103/5 "2007-06-05T04:47:16Z")

</div>

Kenneth McDonald wrote:

> Since a reverse range (eg. 4...1) is functionally almost the same as an empty range, is there an alternative in the standard library, where .each would actually iterate over the elements from first to last, in this case 4, 3, 2?

I can't resist this one...

class Range  
&nbsp;&nbsp;&nbsp;def reverse  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r = dup  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def r.each(&block)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;last.downto(first, &block)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r  
&nbsp;&nbsp;&nbsp;end  
end

\>\> (1..9).to\_a  
=\> [1, 2, 3, 4, 5, 6, 7, 8, 9]  
\>\> (1..9).reverse.to\_a  
=\> [9, 8, 7, 6, 5, 4, 3, 2, 1]

😃

Daniel

---

<div class="post-metadata">

### Author: ![7rans](https://avatars.discourse-cdn.com/v4/letter/7/a8b319/32.png) [@7rans](https://rubytalk.org/u/7rans)
#### Post date: [5 June 2007 05:30 UTC](https://rubytalk.org/t/reverse-range-alternatives/38103/6 "2007-06-05T05:30:03Z")

</div>

Would be nice if Range supported this. It would mean working off a  
#pred, not just #succ. It's been a while since I've messed with it,  
but I'm pretty sure Facets' Interval class does this.

For a lite solution however you might consider:

&nbsp;&nbsp;(-4..-1).each { |i| i.abs }

T.

> **···**
>
> On Jun 4, 4:51 pm, Kenneth McDonald \<kenneth.m.mcdon...@sbcglobal.net\> wrote:
> 
> > Since a reverse range (eg. 4...1) is functionally almost the same as an  
> > empty range, is there an alternative in the standard library, where  
> > .each would actually iterate over the elements from first to last, in  
> > this case 4, 3, 2?

---

<div class="post-metadata">

### Author: ![Kenneth\_McDonald](https://avatars.discourse-cdn.com/v4/letter/k/dc4da7/32.png) [@Kenneth\_McDonald](https://rubytalk.org/u/Kenneth_McDonald)
#### Post date: [4 June 2007 22:07 UTC](https://rubytalk.org/t/reverse-range-alternatives/38103/7 "2007-06-04T22:07:05Z")

</div>

fREW wrote:

> **···**
>
> > On 6/4/07, Kenneth McDonald \<kenneth.m.mcdonald@sbcglobal.net\> wrote:
> > 
> > > Since a reverse range (eg. 4...1) is functionally almost the same as an  
> > > empty range, is there an alternative in the standard library, where  
> > > .each would actually iterate over the elements from first to last, in  
> > > this case 4, 3, 2?
> > > 
> > > Thanks,  
> > > Ken
> > 
> > You could do 4.downto(2) { |i| ... }
> 
> Oh, of course. I'm still not entirely used to thinking of numbers as having a bunch of their own methods. Thanks!
> 
> Ken

---

<div class="post-metadata">

### Author: ![Kenneth\_McDonald](https://avatars.discourse-cdn.com/v4/letter/k/dc4da7/32.png) [@Kenneth\_McDonald](https://rubytalk.org/u/Kenneth_McDonald)
#### Post date: [5 June 2007 05:06 UTC](https://rubytalk.org/t/reverse-range-alternatives/38103/8 "2007-06-05T05:06:39Z")

</div>

I'd thought of that, but it's simply too risky. Changing the behavior of something as fundamental as Range could really screw up if another required module counted on that behavior.

Generally, I'll reopen a class to add methods to it, but not to change its behavior.

Too bad, though, that the original Range type didn't have different semantics, if only to throw an exception when given an inverted range.

Cheers,  
Ken

Daniel DeLorme wrote:

> **···**
>
> > Kenneth McDonald wrote:
> > 
> > > Since a reverse range (eg. 4...1) is functionally almost the same as an empty range, is there an alternative in the standard library, where .each would actually iterate over the elements from first to last, in this case 4, 3, 2?
> > 
> > I can't resist this one...
> > 
> > class Range  
> > &nbsp;&nbsp;def reverse  
> > &nbsp;&nbsp;&nbsp;&nbsp;r = dup  
> > &nbsp;&nbsp;&nbsp;&nbsp;def r.each(&block)  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;last.downto(first, &block)  
> > &nbsp;&nbsp;&nbsp;&nbsp;end  
> > &nbsp;&nbsp;&nbsp;&nbsp;r  
> > &nbsp;&nbsp;end  
> > end
> > 
> > \>\> (1..9).to\_a  
> > =\> [1, 2, 3, 4, 5, 6, 7, 8, 9]  
> > \>\> (1..9).reverse.to\_a  
> > =\> [9, 8, 7, 6, 5, 4, 3, 2, 1]
> > 
> > 😃
> > 
> > Daniel

---

<div class="post-metadata">

### Author: ![Rick\_DeNatale1](https://avatars.discourse-cdn.com/v4/letter/r/bbce88/32.png) [@Rick\_DeNatale1](https://rubytalk.org/u/Rick_DeNatale1)
#### Post date: [5 June 2007 21:02 UTC](https://rubytalk.org/t/reverse-range-alternatives/38103/9 "2007-06-05T21:02:08Z")

</div>

First let me take the liberty of reversing the top posting:

> Daniel DeLorme wrote:  
> \>  
> \> I can't resist this one...  
> \>  
> \> class Range  
> \> def reverse  
> \> r = dup  
> \> def r.each(&block)  
> \> last.downto(first, &block)  
> \> end  
> \> r  
> \> end  
> \> end
> 
> I'd thought of that, but it's simply too risky. Changing the behavior of  
> something as fundamental as Range could really screw up if another  
> required module counted on that behavior.
> 
> Generally, I'll reopen a class to add methods to it, but not to change  
> its behavior.

Actually if you look carefully that's what his code does. He added a  
method to range which returns a new instance of range with a singleton  
method which overrides each. Normal instances of range won't be  
affected.

It's a nice usage of the nested method definitions we were discussing recently.

Bravo Daniel.

Of course the reversed range should probably also invariants like:

&nbsp;&nbsp;&nbsp;&nbsp;(1..3).reverse.last == (1..3).reverse.to\_a.last

And methods like to\_s and step should also do the right thing too.

If you want to go that far it's probably better to have a ReverseRange  
class and have the Range#reverse return an instance of that.

> **···**
>
> On 6/5/07, Kenneth McDonald \<kenneth.m.mcdonald@sbcglobal.net\> wrote:
> 
> --  
> Rick DeNatale
> 
> My blog on Ruby  
> [http://talklikeaduck.denhaven2.com/](http://talklikeaduck.denhaven2.com/)

---

<div class="post-metadata">

### Author: ![Kenneth\_McDonald](https://avatars.discourse-cdn.com/v4/letter/k/dc4da7/32.png) [@Kenneth\_McDonald](https://rubytalk.org/u/Kenneth_McDonald)
#### Post date: [5 June 2007 22:40 UTC](https://rubytalk.org/t/reverse-range-alternatives/38103/10 "2007-06-05T22:40:10Z")

</div>

Oops, my bad, I saw the class being reopened and jumped to a conclusion without even looking at the code. Thanks for pointing this out.

But I still wish it were possible to write (3...1) and have it do something that (IMHO) would be a bit more useful than the current behavior. 🙂 Oh well, too late now.

K

Rick DeNatale wrote:

> **···**
>
> > First let me take the liberty of reversing the top posting:  
> > On 6/5/07, Kenneth McDonald \<kenneth.m.mcdonald@sbcglobal.net\> wrote:
> > 
> > > Daniel DeLorme wrote:  
> > > \>  
> > > \> I can't resist this one...  
> > > \>  
> > > \> class Range  
> > > \> def reverse  
> > > \> r = dup  
> > > \> def r.each(&block)  
> > > \> last.downto(first, &block)  
> > > \> end  
> > > \> r  
> > > \> end  
> > > \> end
> > > 
> > > I'd thought of that, but it's simply too risky. Changing the behavior of  
> > > something as fundamental as Range could really screw up if another  
> > > required module counted on that behavior.
> > > 
> > > Generally, I'll reopen a class to add methods to it, but not to change  
> > > its behavior.
> > 
> > Actually if you look carefully that's what his code does. He added a  
> > method to range which returns a new instance of range with a singleton  
> > method which overrides each. Normal instances of range won't be  
> > affected.
> > 
> > It's a nice usage of the nested method definitions we were discussing recently.
> > 
> > Bravo Daniel.
> > 
> > Of course the reversed range should probably also invariants like:
> > 
> > &nbsp;&nbsp;&nbsp;(1..3).reverse.last == (1..3).reverse.to\_a.last
> > 
> > And methods like to\_s and step should also do the right thing too.
> > 
> > If you want to go that far it's probably better to have a ReverseRange  
> > class and have the Range#reverse return an instance of that.

---

<div class="post-metadata">

### Author: ![Robert\_K1](https://yyz1.discourse-cdn.com/flex029/user_avatar/rubytalk.org/robert_k1/32/1830_2.png) [@Robert\_K1](https://rubytalk.org/u/Robert_K1)
#### Post date: [6 June 2007 08:50 UTC](https://rubytalk.org/t/reverse-range-alternatives/38103/11 "2007-06-06T08:50:53Z")

</div>

> Oops, my bad, I saw the class being reopened and jumped to a conclusion without even looking at the code. Thanks for pointing this out.
> 
> But I still wish it were possible to write (3...1) and have it do something that (IMHO) would be a bit more useful than the current behavior. 🙂 Oh well, too late now.

The real issue here is that there are at least two useful ways to deal with ranges where the second element lies before the first one:

1. no iteration

This is useful for scenarios where you somehow determine the end point and you want to iterate only if it is to the right of the starting point. For example

def show\_silly\_example(s, start, char)  
&nbsp;&nbsp;&nbsp;(start .. s.index(char)).each do |i|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts s[i]  
&nbsp;&nbsp;&nbsp;end  
end

2. backwards iteration

This is useful when you want to be able to do backward iteration.

Given the fact that not foo all possible range endpoints there is a meaningful #pred method, I guess option 1 is actually a better choice:

irb(main):012:0\> "ab".succ  
=\> "ac"  
irb(main):013:0\> "ab".pred  
NoMethodError: undefined method `pred' for "ab":String  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;from (irb):13  
irb(main):014:0\>

IMHO a ReverseRange class would be good, but at the moment I cannot think of a compelling syntax that would make creation as straightforward as for Range.

Kind regards

&nbsp;&nbsp;robert

> **···**
>
> On 06.06.2007 00:40, Kenneth McDonald wrote:  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;from :0
