# Prob with ranges

**URL:** <https://www.ruby-forum.com/t/prob-with-ranges/151264>\
**Category:** Ruby\
**Created:** [October 19, 2008, 1:30am UTC](https://www.ruby-forum.com/t/prob-with-ranges/151264 "2008-10-19T01:30:40Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Junkone](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/e274bd/32.png) [@Junkone](https://www.ruby-forum.com/u/Junkone)\
**Post date:** [October 19, 2008, 1:30am UTC](https://www.ruby-forum.com/t/prob-with-ranges/151264/1 "2008-10-19T01:30:40Z")

</div>

i looked at an example  
rng.each {| i | block } -\> rng

Iterates over the elements rng, passing each in turn to the block.

(10…15).each do |n|  
print n, ’ ’  
end

produces: 10 11 12 13 14 15

when i try the same, it does not work. here is my attempt.  
irb(main):025:0\> (15…10).each do |n|  
irb(main):026:1\* print n  
irb(main):027:1\> end  
=\> 15…10  
irb(main):028:0\> (5…10).each do |n|  
irb(main):029:1\* print n  
irb(main):030:1\> end  
5678910=\> 5…10  
irb(main):031:0\>

---

<div class="post-metadata">

**Author:** ![Junkone](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/e274bd/32.png) [@Junkone](https://www.ruby-forum.com/u/Junkone)\
**Post date:** [October 19, 2008, 1:52am UTC](https://www.ruby-forum.com/t/prob-with-ranges/151264/2 "2008-10-19T01:52:17Z")

</div>

On Sat, Oct 18, 2008 at 7:29 PM, Junkone [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> produces: 10 11 12 13 14 15  
> irb(main):028:0\> (5…10).each do |n|  
> irb(main):029:1\* print n  
> irb(main):030:1\> end  
> 5678910=\> 5…10  
> irb(main):031:0\>

yes it does, you just forgot the separator in your call to print

(5…10).each do |n|  
print n, ’ ’  
end

puts n  
will give you a newline.

---

<div class="post-metadata">

**Author:** ![Junkone](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/e274bd/32.png) [@Junkone](https://www.ruby-forum.com/u/Junkone)\
**Post date:** [October 19, 2008, 10:15am UTC](https://www.ruby-forum.com/t/prob-with-ranges/151264/3 "2008-10-19T10:15:49Z")

</div>

Junkone wrote:

> irb(main):025:0\> (15…10).each do |n|  
> irb(main):026:1\* print n  
> irb(main):027:1\> end  
> =\> 15…10

That doesn’t work because 15…10 is an empty range.

> irb(main):028:0\> (5…10).each do |n|  
> irb(main):029:1\* print n  
> irb(main):030:1\> end  
> 5678910=\> 5…10

That does work. It did print the numbers right there in front of the =\>

HTH,  
Sebastian

---

<div class="post-metadata">

**Author:** ![Junkone](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/e274bd/32.png) [@Junkone](https://www.ruby-forum.com/u/Junkone)\
**Post date:** [October 19, 2008, 6:05pm UTC](https://www.ruby-forum.com/t/prob-with-ranges/151264/4 "2008-10-19T18:05:48Z")

</div>

so i cannot have a range that is decreasing in numbers. for eg  
1…5 can be 1,2,3,4,5  
how can i do 5…1 ie 5,4,3,2,1

On Oct 19, 4:14 am, Sebastian H. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)

---

<div class="post-metadata">

**Author:** ![Junkone](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/e274bd/32.png) [@Junkone](https://www.ruby-forum.com/u/Junkone)\
**Post date:** [October 19, 2008, 7:02pm UTC](https://www.ruby-forum.com/t/prob-with-ranges/151264/5 "2008-10-19T19:02:17Z")

</div>

Junkone wrote:

> so i cannot have a range that is decreasing in numbers. for eg  
> 1…5 can be 1,2,3,4,5  
> how can i do 5…1 ie 5,4,3,2,1

Range is by definition increasing. If you want to iterate over numbers  
from 5 to 1, you can do it like this: (1…5).to\_a.reverse.each or better  
(1…5).to\_a.reverse\_each (this does not allocate the reversed array,  
just iterates in the opposite order). Both these methods allocate the  
array of all the values, though, so if your range is big, you should  
probably use an explicit loop with a decremented value and a stop  
condition.

TPR.

---

<div class="post-metadata">

**Author:** ![Junkone](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/e274bd/32.png) [@Junkone](https://www.ruby-forum.com/u/Junkone)\
**Post date:** [October 19, 2008, 7:11pm UTC](https://www.ruby-forum.com/t/prob-with-ranges/151264/6 "2008-10-19T19:11:05Z")

</div>

On Oct 19, 2008, at 11:04 AM, Junkone wrote:

> so i cannot have a range that is decreasing in numbers. for eg  
> 1…5 can be 1,2,3,4,5  
> how can i do 5…1 ie 5,4,3,2,1

5.downto(1) do |i|  
puts i  
end

---

<div class="post-metadata">

**Author:** ![Junkone](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/e274bd/32.png) [@Junkone](https://www.ruby-forum.com/u/Junkone)\
**Post date:** [October 19, 2008, 7:12pm UTC](https://www.ruby-forum.com/t/prob-with-ranges/151264/7 "2008-10-19T19:12:15Z")

</div>

Junkone wrote:

> so i cannot have a range that is decreasing in numbers. for eg  
> 1…5 can be 1,2,3,4,5  
> how can i do 5…1 ie 5,4,3,2,1

ri Integer#downto

---

<div class="post-metadata">

**Author:** ![Junkone](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/e274bd/32.png) [@Junkone](https://www.ruby-forum.com/u/Junkone)\
**Post date:** [October 21, 2008, 4:22am UTC](https://www.ruby-forum.com/t/prob-with-ranges/151264/8 "2008-10-21T04:22:18Z")

</div>

Junkone wrote:

> irb(main):025:0\> (15…10).each do |n|  
> irb(main):026:1\* print n  
> irb(main):027:1\> end  
> =\> 15…10

I used this as a self-tutorial for learning RSpec for the first time.

% spec ./specification -fs

Synopsis

- (3…7).to\_a #=\> [3, 4, 5, 6, 7]
- (7…3).to\_a #=\> []
- reversible(3…7).to\_a #=\> [3, 4, 5, 6, 7]
- reversible(7…3).to\_a #=\> [7, 6, 5, 4, 3]

A forward-pointing Range (3…7) with r.exclude\_end? == false

- has invariant reversible(r) == r
- has invariant reversible(r).object\_id == r.object\_id

A backward-pointing Range (7…3) with r.exclude\_end? == false

- has invariant reversible(r) == ReverseRange.new(r.begin, r.end)

A forward-pointing Range (3…7) with r.exclude\_end? == true

- is accepted by reversible()

A backward-pointing Range (7…3) with r.exclude\_end? == true

- is rejected by reversible()

ReverseRange instances are normally created with reversible()

- reversible(7…3) #=\> ReverseRange.new(7, 3)

ReverseRange behaves similarly to Range

- reversible(7…3).inspect #=\> ‘#\<ReverseRange 7…3\>’
- reversible(7…3).first #=\> 7
- reversible(7…3).last #=\> 3
- reversible(7…3).include?(9) #=\> false
- reversible(7…3).member?(4) #=\> true
- reversible(7…3).include?(4) #=\> true
- (7…3).include?(4) #=\> false
- has the same case/when semantics as Range

ReverseRange can also be passed to reversible()

- ReverseRange.new(3, 7).to\_a #=\> []
- reversible(ReverseRange.new(3, 7)).to\_a #=\> [3, 4, 5, 6, 7]
- reversible(ReverseRange.new(3, 7)).is\_a?(Range) #=\> true
- reversible(ReverseRange.new(7, 3)).is\_a?(ReverseRange) #=\> true

ReverseRange#step(n)

- argument n must be negative
- reversible(7…3).to\_enum(:step, -1).to\_a #=\> [7, 6, 5, 4, 3]
- reversible(7…3).to\_enum(:step, -2).to\_a #=\> [7, 5, 3]
- reversible(7…3).to\_enum(:step, -3).to\_a #=\> [7, 4]
- reversible(7…3).to\_enum(:step, -4).to\_a #=\> [7, 3]
- reversible(7…3).to\_enum(:step, -5).to\_a #=\> [7]
- reversible(7…3).to\_enum(:step, -99).to\_a #=\> [7]

ReverseRange#step(n) with simple one-character String#pred

- reversible(‘t’…‘p’).to\_enum(:step, -1).to\_a #=\> %w[t s r q p]
- reversible(‘t’…‘p’).to\_enum(:step, -2).to\_a #=\> %w[t r p]
- reversible(‘t’…‘p’).to\_enum(:step, -3).to\_a #=\> %w[t q]
- reversible(‘t’…‘p’).to\_enum(:step, -4).to\_a #=\> %w[t p]
- reversible(‘t’…‘p’).to\_enum(:step, -5).to\_a #=\> %w[t]
- reversible(‘t’…‘p’).to\_enum(:step, -99).to\_a #=\> %w[t]

ReverseRange details

- has invariant r == r
- has invariant r == ReverseRange.new(r.begin, r.end)
- has invariant r.eql?(r) == true
- has invariant r.eql?(ReverseRange.new(r.begin, r.end)) == true
- has invariant r.exclude\_end? == false
- has invariant r.inspect == r.to\_s
- calls #pred on elements
- leaves #pred definition to the user

reversible()

- accepts Range object
- accepts Range-quacking object
- fails if argument does not quack like Range

Finished in 0.029019 seconds

46 examples, 0 failures

[http://github.com/quix/reverse\_range/tree/master](http://github.com/quix/reverse_range/tree/master)

Past-endpoint ranges (7…3) seemed too ambiguous, so I just disallowed  
it. In particular if (3…5).to\_a == [3, 4], then  
reversible(5…3).to\_a == [4, 3]. Do not want.

I considered using the name ‘magnetic’ instead of ‘reversible’, as it  
has the effect of flipping around to find the right polarity.

James M. Lawrence

---

<div class="post-metadata">

**Author:** ![Junkone](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/e274bd/32.png) [@Junkone](https://www.ruby-forum.com/u/Junkone)\
**Post date:** [October 21, 2008, 2:41pm UTC](https://www.ruby-forum.com/t/prob-with-ranges/151264/9 "2008-10-21T14:41:52Z")

</div>

James M. Lawrence wrote:

> I used this as a self-tutorial for learning RSpec for the first time.
> 
> % spec ./specification.rb -fs
> 
> Synopsis
> 
> - (3…7).to\_a #=\> [3, 4, 5, 6, 7]
> - (7…3).to\_a #=\> []
> - reversible(3…7).to\_a #=\> [3, 4, 5, 6, 7]
> - reversible(7…3).to\_a #=\> [7, 6, 5, 4, 3]
> 
> […]

I received an email which indicated this needs some explanation. Yes,  
this is the RSpec output. I give it an equation, run it through RSpec,  
then transform it as above. So in this case the test and the  
documentation are the same thing.
