# Intervals in Ruby

**URL:** <https://rubytalk.org/t/intervals-in-ruby/41651>\
**Category:** ruby-talk\
**Created:** [25 October 2007 01:45 UTC](https://rubytalk.org/t/intervals-in-ruby/41651 "2007-10-25T01:45:02Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Steven\_D\_Aprano](https://avatars.discourse-cdn.com/v4/letter/s/dc4da7/32.png) [@Steven\_D\_Aprano](https://rubytalk.org/u/Steven_D_Aprano)\
**Post date:** [25 October 2007 01:45 UTC](https://rubytalk.org/t/intervals-in-ruby/41651/1 "2007-10-25T01:45:02Z")

</div>

Howdy,

I'm not a Ruby developer \*at all\*, I use Python, but this is not flame-  
bait. I'm interested in how Ruby folks find using intervals.

In Python, we deal with integer ranges virtually exclusively with the  
range() function. range() always results in a half-open interval:

range(5) =\> 0, 1, 2, 3, 4  
range(1, 5) =\> 1, 2, 3, 4  
range(4, -1, -1) =\> 4, 3, 2, 1, 0

The start argument is always included, the end argument is never  
included, and there is an optional step size (defaults to 1).

I understand that in Ruby you have quite a few choices, some of which are  
half-open like Python, some of which are closed:

0..5 =\> 0, 1, 2, 3, 4, 5  
0...5 =\> 0, 1, 2, 3, 4

5.downto(1) =\> 5, 4, 3, 2, 1  
1.upto(5) =\> 1, 2, 3, 4, 5  
5.times() =\> 0, 1, 2, 3, 4  
5.step(11, 3) =\> 5, 8, 11

and the Range.new method.

My question is: how useful are all these different mechanisms? Do you  
find that having two operators .. and ... is a blessing, or a curse  
because you can never remember which is which?

How useful are the closed interval forms? Do you find yourself making off-  
by-one errors or needing to increment/decrement variables by one?

e.g. do you often need to write things like:

start.step(end + 1, increment){| i | block }  
start.step(end - 1, increment){| i | block }

Writing in Python, I almost never need to "shift the fence-posts", so to  
speak. E.g. I virtually never need to write something like:

range(start, end+1)

to avoid an off-by-one error. When I used to program in Pascal (which  
exclusively uses closed intervals) I used to need to do it all the time.  
What's the Ruby experience?

Thank you,

> **···**
>
> --  
> Steven

---

<div class="post-metadata">

**Author:** ![Bob\_Hutchison1](https://avatars.discourse-cdn.com/v4/letter/b/9e8a1a/32.png) [@Bob\_Hutchison1](https://rubytalk.org/u/Bob_Hutchison1)\
**Post date:** [25 October 2007 02:49 UTC](https://rubytalk.org/t/intervals-in-ruby/41651/2 "2007-10-25T02:49:15Z")

</div>

Hi Steven,

> Howdy,
> 
> I'm not a Ruby developer \*at all\*, I use Python, but this is not flame-  
> bait. I'm interested in how Ruby folks find using intervals.

I can only speak for myself.

> In Python, we deal with integer ranges virtually exclusively with the  
> range() function. range() always results in a half-open interval:
> 
> range(5) =\> 0, 1, 2, 3, 4  
> range(1, 5) =\> 1, 2, 3, 4  
> range(4, -1, -1) =\> 4, 3, 2, 1, 0
> 
> The start argument is always included, the end argument is never  
> included, and there is an optional step size (defaults to 1).
> 
> I understand that in Ruby you have quite a few choices, some of which are  
> half-open like Python, some of which are closed:
> 
> 0..5 =\> 0, 1, 2, 3, 4, 5  
> 0...5 =\> 0, 1, 2, 3, 4

You need to write (0..5).to\_a to get an array, though you don't need to convert it to an array for the usual kind of things like looping and choosing elements of an array.

> 5.downto(1) =\> 5, 4, 3, 2, 1  
> 1.upto(5) =\> 1, 2, 3, 4, 5  
> 5.times() =\> 0, 1, 2, 3, 4  
> 5.step(11, 3) =\> 5, 8, 11
> 
> and the Range.new method.

No arrays here either (if that matters to you)

> My question is: how useful are all these different mechanisms? Do you  
> find that having two operators .. and ... is a blessing, or a curse  
> because you can never remember which is which?

I had a look through about 25,000 lines of Ruby I working with now.

I've never used ..., only .. -- and then only for choosing parts of an array.

In my installed gems (about 60k lines but there are multiple versions of some libraries) this seems to happen in 6 files dealing with bigdecimals, telnet, http, webrick (a web server), and in an xml parser. The most interesting use is in a case statement handling HTTP error codes.

> How useful are the closed interval forms? Do you find yourself making off-  
> by-one errors or needing to increment/decrement variables by one?
> 
> e.g. do you often need to write things like:
> 
> start.step(end + 1, increment){| i | block }  
> start.step(end - 1, increment){| i | block }

This does not appear in my code base. I habitually iterate over collections and arrays. I can't recall ever needing the a sequence of integers (except in benchmarks and tests)

Step shows up in the total code base I've got (roughly 80k lines) seven times, downto appears twice. Range.new shows up 4 times and in all cases with true for the third argument (i.e. equivalent to .. rather than ...)

> Writing in Python, I almost never need to "shift the fence-posts", so to  
> speak. E.g. I virtually never need to write something like:
> 
> range(start, end+1)

I have had to do this once in the 25k lines: (3..(ARGV.length - 1)).each -- which, now that you've reminded me is better written (3...ARGV.length).each -- I'll change that now. Thanks.

> to avoid an off-by-one error. When I used to program in Pascal (which  
> exclusively uses closed intervals) I used to need to do it all the time.  
> What's the Ruby experience?

In a few other languages this has definitely been something of an issue. Definitely.

Basically, I don't use that idiom, I iterate over collections. I think other Ruby programmers don't do that either.

Interesting. Thanks. Nice question.

Cheers,  
Bob

> **···**
>
> On 24-Oct-07, at 9:45 PM, Steven D'Aprano wrote:
> 
> > Thank you,
> > 
> > --  
> > Steven
> 
> ----  
> Bob Hutchison -- tumblelog at [http://www.recursive.ca/so/](http://www.recursive.ca/so/)  
> Recursive Design Inc. -- weblog at [http://www.recursive.ca/hutch](http://www.recursive.ca/hutch)  
> [http://www.recursive.ca/](http://www.recursive.ca/) -- works on [http://www.raconteur.info/cms-for-static-content/home/](http://www.raconteur.info/cms-for-static-content/home/)

---

<div class="post-metadata">

**Author:** ![Justin\_Collins](https://avatars.discourse-cdn.com/v4/letter/j/3e96dc/32.png) [@Justin\_Collins](https://rubytalk.org/u/Justin_Collins)\
**Post date:** [25 October 2007 02:53 UTC](https://rubytalk.org/t/intervals-in-ruby/41651/3 "2007-10-25T02:53:26Z")

</div>

Steven D'Aprano wrote:

> Howdy,  
> &nbsp;&nbsp;  
> Hi  
> I'm not a Ruby developer \*at all\*, I use Python, but this is not flame-  
> bait. I'm interested in how Ruby folks find using intervals.
> 
> In Python, we deal with integer ranges virtually exclusively with the range() function. range() always results in a half-open interval:
> 
> range(5) =\> 0, 1, 2, 3, 4  
> range(1, 5) =\> 1, 2, 3, 4  
> range(4, -1, -1) =\> 4, 3, 2, 1, 0
> 
> The start argument is always included, the end argument is never included, and there is an optional step size (defaults to 1).
> 
> I understand that in Ruby you have quite a few choices, some of which are half-open like Python, some of which are closed:
> 
> 0..5 =\> 0, 1, 2, 3, 4, 5  
> 0...5 =\> 0, 1, 2, 3, 4  
> &nbsp;&nbsp;

I nearly always use 0..5  
Sometimes 0...5 in special cases.

> 5.downto(1) =\> 5, 4, 3, 2, 1  
> 1.upto(5) =\> 1, 2, 3, 4, 5  
> 5.times() =\> 0, 1, 2, 3, 4  
> 5.step(11, 3) =\> 5, 8, 11  
> &nbsp;&nbsp;  
> Rarely do I use these. And even then it's only 5.times do ... end

> and the Range.new method.  
> &nbsp;&nbsp;  
> Never.

> My question is: how useful are all these different mechanisms? Do you find that having two operators .. and ... is a blessing, or a curse  
> &nbsp;&nbsp;because you can never remember which is which?  
> &nbsp;&nbsp;  
> Maybe it's just me, but I nearly always use .. so it's easy to remember that ... is the "special" case for me.

> How useful are the closed interval forms? Do you find yourself making off-  
> by-one errors or needing to increment/decrement variables by one?
> 
> e.g. do you often need to write things like:
> 
> start.step(end + 1, increment){| i | block }  
> start.step(end - 1, increment){| i | block }  
> &nbsp;&nbsp;  
> Never.

> Writing in Python, I almost never need to "shift the fence-posts", so to speak. E.g. I virtually never need to write something like:
> 
> range(start, end+1)
> 
> to avoid an off-by-one error. When I used to program in Pascal (which exclusively uses closed intervals) I used to need to do it all the time. What's the Ruby experience?
> 
> Thank you,  
> &nbsp;&nbsp;  
> Maybe I'm unusual (most of my code is for my own pet projects) but nearly all my iteration is done with arrays and hashes or objects that act like them, so my most commonly used loop construct is 'each'. After that it's probably 'until', then 'while', and 'times' last.

That's been my experience.

-Justin

---

<div class="post-metadata">

**Author:** ![Yossef\_Mendelssohn](https://avatars.discourse-cdn.com/v4/letter/y/f19dbf/32.png) [@Yossef\_Mendelssohn](https://rubytalk.org/u/Yossef_Mendelssohn)\
**Post date:** [25 October 2007 02:58 UTC](https://rubytalk.org/t/intervals-in-ruby/41651/4 "2007-10-25T02:58:34Z")

</div>

I can only speak from my own experience.

I came to Ruby from Perl, so I knew .. and ... backwards and forwards.  
There might have been a bit of a stumbling block when I was learning  
Perl, but it's been so long that it all seems natural to me.

And speaking of Perl and "natural", much of that has to do with the  
language's creator/designer being a linguist (or at least people like  
to say so). When I came to Ruby, it felt like Matz took up that cause  
and ran with it. For many problems, there are many, many solutions.  
You choose which one works for you. Methods like Integer#times,  
Integer#downto, Integer#upto, Numeric#step all have their uses.  
Choosing the right one feels like choosing the right word to construct  
a sentence.

> **···**
>
> On Oct 24, 8:45 pm, Steven D'Aprano \<st...@REMOVE-THIS- cybersource.com.au\> wrote:
> 
> > I understand that in Ruby you have quite a few choices, some of which are  
> > half-open like Python, some of which are closed:
> > 
> > 0..5 =\> 0, 1, 2, 3, 4, 5  
> > 0...5 =\> 0, 1, 2, 3, 4
> > 
> > 5.downto(1) =\> 5, 4, 3, 2, 1  
> > 1.upto(5) =\> 1, 2, 3, 4, 5  
> > 5.times() =\> 0, 1, 2, 3, 4  
> > 5.step(11, 3) =\> 5, 8, 11
> > 
> > and the Range.new method.
> > 
> > My question is: how useful are all these different mechanisms? Do you  
> > find that having two operators .. and ... is a blessing, or a curse  
> > because you can never remember which is which?
> 
> --  
> -yossef

---

<div class="post-metadata">

**Author:** ![Andreas\_Haller](https://avatars.discourse-cdn.com/v4/letter/a/2acd7d/32.png) [@Andreas\_Haller](https://rubytalk.org/u/Andreas_Haller)\
**Post date:** [25 October 2007 03:09 UTC](https://rubytalk.org/t/intervals-in-ruby/41651/5 "2007-10-25T03:09:25Z")

</div>

> My question is: how useful are all these different mechanisms? Do you  
> find that having two operators .. and ... is a blessing, or a curse  
> because you can never remember which is which?

Hi  
i think it makes perfect sense to have those two options and with such a similar syntax. I had to think a second everytime to remember which is which, but i got used to it now. (Although it does not make much sense to me that three dots mean "less" than two dots.)

> [...]. range() always results in a half-open interval:  
> range(1, 5) =\> 1, 2, 3, 4

I had to look up the terms "half-open" and "half-closed". [Interval (mathematics) - Wikipedia](http://en.wikipedia.org/wiki/Interval_(mathematics)) says that an half-open interval (2,4] excludes 2, but includes 4. So in Python that would be half-closed intervals by default (right?), ikewise in Ruby.

I did not know upto() and downto() Uups.  
Together with n.times they are just nice to have and you can use the one message that would be the most expressive, depending what you want to write.

What i find strage about ranges is that:  
(0..3).to\_a # =\> [0, 1, 2, 3]  
but  
(3..0).to\_a # =\>

Regarding the "off-by-one" question, i dont really know.

andreas

> **···**
>
> Am 25.10.2007 um 03:45 schrieb Steven D'Aprano:
> 
> > Howdy,
> > 
> > I'm not a Ruby developer \*at all\*, I use Python, but this is not flame-  
> > bait. I'm interested in how Ruby folks find using intervals.
> > 
> > In Python, we deal with integer ranges virtually exclusively with the  
> > range() function. range() always results in a half-open interval:
> > 
> > range(5) =\> 0, 1, 2, 3, 4  
> > range(1, 5) =\> 1, 2, 3, 4  
> > range(4, -1, -1) =\> 4, 3, 2, 1, 0
> > 
> > The start argument is always included, the end argument is never  
> > included, and there is an optional step size (defaults to 1).
> > 
> > I understand that in Ruby you have quite a few choices, some of which are  
> > half-open like Python, some of which are closed:
> > 
> > 0..5 =\> 0, 1, 2, 3, 4, 5  
> > 0...5 =\> 0, 1, 2, 3, 4
> > 
> > 5.downto(1) =\> 5, 4, 3, 2, 1  
> > 1.upto(5) =\> 1, 2, 3, 4, 5  
> > 5.times() =\> 0, 1, 2, 3, 4  
> > 5.step(11, 3) =\> 5, 8, 11
> > 
> > and the Range.new method.
> > 
> > My question is: how useful are all these different mechanisms? Do you  
> > find that having two operators .. and ... is a blessing, or a curse  
> > because you can never remember which is which?
> > 
> > How useful are the closed interval forms? Do you find yourself making off-  
> > by-one errors or needing to increment/decrement variables by one?
> > 
> > e.g. do you often need to write things like:
> > 
> > start.step(end + 1, increment){| i | block }  
> > start.step(end - 1, increment){| i | block }
> > 
> > Writing in Python, I almost never need to "shift the fence-posts", so to  
> > speak. E.g. I virtually never need to write something like:
> > 
> > range(start, end+1)
> > 
> > to avoid an off-by-one error. When I used to program in Pascal (which  
> > exclusively uses closed intervals) I used to need to do it all the time.  
> > What's the Ruby experience?
> > 
> > Thank you,
> > 
> > --  
> > Steven

---

<div class="post-metadata">

**Author:** ![Michael\_Ulm](https://avatars.discourse-cdn.com/v4/letter/m/a9adbd/32.png) [@Michael\_Ulm](https://rubytalk.org/u/Michael_Ulm)\
**Post date:** [25 October 2007 06:40 UTC](https://rubytalk.org/t/intervals-in-ruby/41651/6 "2007-10-25T06:40:00Z")

</div>

Steven D'Aprano wrote:

> Howdy,
> 
> I'm not a Ruby developer \*at all\*, I use Python, but this is not flame-  
> bait. I'm interested in how Ruby folks find using intervals.
> 
> In Python, we deal with integer ranges virtually exclusively with the range() function. range() always results in a half-open interval:
> 
> range(5) =\> 0, 1, 2, 3, 4  
> range(1, 5) =\> 1, 2, 3, 4  
> range(4, -1, -1) =\> 4, 3, 2, 1, 0
> 
> The start argument is always included, the end argument is never included, and there is an optional step size (defaults to 1).

If there is only one kind of range to be supported (which I understand  
to be in sync with the Python philosophy), I agree that half-open  
intervals are the way to go.

> I understand that in Ruby you have quite a few choices, some of which are half-open like Python, some of which are closed:
> 
> 0..5 =\> 0, 1, 2, 3, 4, 5  
> 0...5 =\> 0, 1, 2, 3, 4

The two different ranges are nice-to-have, because sometimes the closed  
interval is the right thing to use. I'd have exchanged the syntax 'though.  
Having said that, I have never had a problem distinguishing the two.

> 5.downto(1) =\> 5, 4, 3, 2, 1  
> 1.upto(5) =\> 1, 2, 3, 4, 5  
> 5.times() =\> 0, 1, 2, 3, 4  
> 5.step(11, 3) =\> 5, 8, 11

--snip--

This is not really a range, but the Ruby Way of looping; it is what made me  
fall in love with Ruby in the first place. For me, it is one the most  
beautiful aspects of any programming language that I know.

Best regards,

Michael

---

<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:** [25 October 2007 06:40 UTC](https://rubytalk.org/t/intervals-in-ruby/41651/7 "2007-10-25T06:40:09Z")

</div>

I rarely use #downto, #upto and #step. I frequently use #times and ranges - usually the ".." version but sometimes also the other one. I never use Range.new.

Both range versions come in handy, for example, if you need to iterate through an array using an index counter then the triple dot is convenient because you do not need to to math:

for i in 0...ar.size  
&nbsp;&nbsp;&nbsp;puts ar[i]  
end

#times is an alternative here

ar.size.times do |i|  
&nbsp;&nbsp;&nbsp;puts ar[i]  
end

I think Justing pinpointed the major reason why these integer iterating constructs are less use in Ruby: collections are typically traversed via their #each method.

Kind regards

&nbsp;&nbsp;robert

> **···**
>
> On 25.10.2007 03:43, Steven D'Aprano wrote:
> 
> > Howdy,
> > 
> > I'm not a Ruby developer \*at all\*, I use Python, but this is not flame-  
> > bait. I'm interested in how Ruby folks find using intervals.
> > 
> > In Python, we deal with integer ranges virtually exclusively with the range() function. range() always results in a half-open interval:
> > 
> > range(5) =\> 0, 1, 2, 3, 4  
> > range(1, 5) =\> 1, 2, 3, 4  
> > range(4, -1, -1) =\> 4, 3, 2, 1, 0
> > 
> > The start argument is always included, the end argument is never included, and there is an optional step size (defaults to 1).
> > 
> > I understand that in Ruby you have quite a few choices, some of which are half-open like Python, some of which are closed:
> > 
> > 0..5 =\> 0, 1, 2, 3, 4, 5  
> > 0...5 =\> 0, 1, 2, 3, 4
> > 
> > 5.downto(1) =\> 5, 4, 3, 2, 1  
> > 1.upto(5) =\> 1, 2, 3, 4, 5  
> > 5.times() =\> 0, 1, 2, 3, 4  
> > 5.step(11, 3) =\> 5, 8, 11
> > 
> > and the Range.new method.
> > 
> > My question is: how useful are all these different mechanisms? Do you find that having two operators .. and ... is a blessing, or a curse because you can never remember which is which?
> > 
> > How useful are the closed interval forms? Do you find yourself making off-  
> > by-one errors or needing to increment/decrement variables by one?
> > 
> > e.g. do you often need to write things like:
> > 
> > start.step(end + 1, increment){| i | block }  
> > start.step(end - 1, increment){| i | block }
> > 
> > Writing in Python, I almost never need to "shift the fence-posts", so to speak. E.g. I virtually never need to write something like:
> > 
> > range(start, end+1)
> > 
> > to avoid an off-by-one error. When I used to program in Pascal (which exclusively uses closed intervals) I used to need to do it all the time. What's the Ruby experience?

---

<div class="post-metadata">

**Author:** ![Just\_Another\_Victim1](https://avatars.discourse-cdn.com/v4/letter/j/e56c9b/32.png) [@Just\_Another\_Victim1](https://rubytalk.org/u/Just_Another_Victim1)\
**Post date:** [25 October 2007 07:30 UTC](https://rubytalk.org/t/intervals-in-ruby/41651/8 "2007-10-25T07:30:12Z")

</div>

"Steven D'Aprano" \<steve@REMOVE-THIS-cybersource.com.au\> wrote in message  
news:13hvt65e4d1vd0b@corp.supernews.com...

> Howdy,
> 
> How useful are the closed interval forms? Do you find yourself making off-  
> by-one errors or needing to increment/decrement variables by one?
> 
> e.g. do you often need to write things like:
> 
> start.step(end + 1, increment){| i | block }  
> start.step(end - 1, increment){| i | block }
> 
> Writing in Python, I almost never need to "shift the fence-posts", so to  
> speak. E.g. I virtually never need to write something like:
> 
> range(start, end+1)
> 
> to avoid an off-by-one error. When I used to program in Pascal (which  
> exclusively uses closed intervals) I used to need to do it all the time.  
> What's the Ruby experience?

&nbsp;&nbsp;&nbsp;&nbsp;They're obviously not used a lot but they can be useful.  
&nbsp;&nbsp;&nbsp;&nbsp;They're really for times when you know the start and end points of  
indexing, rather than the start and length of indexing. My girlfriend in  
highschool (who was wonderfully nerdy) was well aware of off-by-one errors  
while not being a computer programmer (she was into math and physics and  
went into engineering) because of problems like asking how many days someone  
has stayed somewhere if they arrived on the 5'th and left on the 16'th. The  
naive answer, of course, is 16 - 5 but, upon closer inspection, it would  
actually be 16 - 5 + 1. Apparently, this pattern has happened to her more  
than once 'cause it came up (somehow) and she brought alot of attention to  
this fact, so much so that I still remember this and am relaying it to all  
of you...  
&nbsp;&nbsp;&nbsp;&nbsp;So, in Python, if you wanted to access the fifth to sixteenth element in  
an array, you'd need to do something like this:

for i in range(5, 16 + 1):  
&nbsp;&nbsp;&nbsp;&nbsp;array[i] # do something with this...

&nbsp;&nbsp;&nbsp;&nbsp;Some people might be tempted to just stick 17 in there but I wouldn't...

---

<div class="post-metadata">

**Author:** ![David\_A\_Black1](https://avatars.discourse-cdn.com/v4/letter/d/bcef8e/32.png) [@David\_A\_Black1](https://rubytalk.org/u/David_A_Black1)\
**Post date:** [25 October 2007 09:46 UTC](https://rubytalk.org/t/intervals-in-ruby/41651/9 "2007-10-25T09:46:10Z")

</div>

Hi --

> Howdy,
> 
> I'm not a Ruby developer \*at all\*, I use Python, but this is not flame-  
> bait. I'm interested in how Ruby folks find using intervals.
> 
> In Python, we deal with integer ranges virtually exclusively with the  
> range() function. range() always results in a half-open interval:
> 
> range(5) =\> 0, 1, 2, 3, 4  
> range(1, 5) =\> 1, 2, 3, 4  
> range(4, -1, -1) =\> 4, 3, 2, 1, 0
> 
> The start argument is always included, the end argument is never  
> included, and there is an optional step size (defaults to 1).
> 
> I understand that in Ruby you have quite a few choices, some of which are  
> half-open like Python, some of which are closed:
> 
> 0..5 =\> 0, 1, 2, 3, 4, 5  
> 0...5 =\> 0, 1, 2, 3, 4
> 
> 5.downto(1) =\> 5, 4, 3, 2, 1  
> 1.upto(5) =\> 1, 2, 3, 4, 5  
> 5.times() =\> 0, 1, 2, 3, 4  
> 5.step(11, 3) =\> 5, 8, 11
> 
> and the Range.new method.
> 
> My question is: how useful are all these different mechanisms? Do you  
> find that having two operators .. and ... is a blessing, or a curse  
> because you can never remember which is which?

They're both useful. Don't forget that a range is not really a  
collection (though some ranges can masquerade as arrays) as a kind of  
boolean inclusion tester. The exclusive version (...) is like having \<  
as well as \<= as a comparison operator -- very handy 🙂

As for the various methods above, I use times quite a bit, downto and  
upto and step not all that often (but I wouldn't be surprised if there  
are cases where I might have used them but didn't think of it).

> How useful are the closed interval forms? Do you find yourself making off-  
> by-one errors or needing to increment/decrement variables by one?
> 
> e.g. do you often need to write things like:
> 
> start.step(end + 1, increment){| i | block }  
> start.step(end - 1, increment){| i | block }
> 
> Writing in Python, I almost never need to "shift the fence-posts", so to  
> speak. E.g. I virtually never need to write something like:
> 
> range(start, end+1)
> 
> to avoid an off-by-one error. When I used to program in Pascal (which  
> exclusively uses closed intervals) I used to need to do it all the time.  
> What's the Ruby experience?

It all depends where the endpoints are coming from. If I can control  
the end one, then I don't have to change it. If I don't, then I do.  
I don't think it's any different from any other such situation --  
e.g.:

&nbsp;&nbsp;&nbsp;items.each\_with\_index do |item,index|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts "Item #{index + 1}: #{item.description}"  
&nbsp;&nbsp;&nbsp;end

It's more about the problem space than the Ruby methods you're using.

David

> **···**
>
> On Thu, 25 Oct 2007, Steven D'Aprano wrote:
> 
> --  
> Upcoming training by David A. Black/Ruby Power and Light, LLC:  
> &nbsp;&nbsp;&nbsp;\* Advancing With Rails, Edison, NJ, November 6-9  
> &nbsp;&nbsp;&nbsp;\* Advancing With Rails, Berlin, Germany, November 19-22  
> &nbsp;&nbsp;&nbsp;\* Intro to Rails, London, UK, December 3-6 (by Skills Matter)  
> See [http://www.rubypal.com](http://www.rubypal.com) for details!

---

<div class="post-metadata">

**Author:** ![Steven\_D\_Aprano](https://avatars.discourse-cdn.com/v4/letter/s/dc4da7/32.png) [@Steven\_D\_Aprano](https://rubytalk.org/u/Steven_D_Aprano)\
**Post date:** [25 October 2007 10:00 UTC](https://rubytalk.org/t/intervals-in-ruby/41651/10 "2007-10-25T10:00:14Z")

</div>

> I understand that in Ruby you have quite a few choices, some of which  
> are half-open like Python, some of which are closed:

...

> My question is: how useful are all these different mechanisms? Do you  
> find that having two operators .. and ... is a blessing, or a curse  
> because you can never remember which is which?
> 
> How useful are the closed interval forms? Do you find yourself making  
> off- by-one errors or needing to increment/decrement variables by one?

Thank you for everyone who wrote back, all good food for thought.

Are there many (any?) good examples of where you need to iterate over an  
integer count, rather than directly over a data structure?

> **···**
>
> On Thu, 25 Oct 2007 01:43:33 +0000, Steven D'Aprano wrote:
> 
> --  
> Steven

---

<div class="post-metadata">

**Author:** ![a11](https://yyz1.discourse-cdn.com/flex029/user_avatar/rubytalk.org/a11/32/8169_2.png) [@a11](https://rubytalk.org/u/a11)\
**Post date:** [25 October 2007 20:53 UTC](https://rubytalk.org/t/intervals-in-ruby/41651/11 "2007-10-25T20:53:34Z")

</div>

> Howdy,
> 
> I'm not a Ruby developer \*at all\*, I use Python, but this is not flame-  
> bait. I'm interested in how Ruby folks find using intervals.
> 
> In Python, we deal with integer ranges virtually exclusively with the  
> range() function. range() always results in a half-open interval:
> 
> range(5) =\> 0, 1, 2, 3, 4  
> range(1, 5) =\> 1, 2, 3, 4  
> range(4, -1, -1) =\> 4, 3, 2, 1, 0
> 
> The start argument is always included, the end argument is never  
> included, and there is an optional step size (defaults to 1).
> 
> I understand that in Ruby you have quite a few choices, some of which are  
> half-open like Python, some of which are closed:
> 
> 0..5 =\> 0, 1, 2, 3, 4, 5  
> 0...5 =\> 0, 1, 2, 3, 4
> 
> 5.downto(1) =\> 5, 4, 3, 2, 1  
> 1.upto(5) =\> 1, 2, 3, 4, 5  
> 5.times() =\> 0, 1, 2, 3, 4  
> 5.step(11, 3) =\> 5, 8, 11
> 
> and the Range.new method.
> 
> My question is: how useful are all these different mechanisms? Do you  
> find that having two operators .. and ... is a blessing, or a curse  
> because you can never remember which is which?

i use both frequently. '...' is always leads to shorter code when complex iterations are done and, of course, lead to fewer off by one errors since ruby arrays are zero index based.

> How useful are the closed interval forms? Do you find yourself making off-  
> by-one errors or needing to increment/decrement variables by one?

no. but i've fixed alot of code that has.

> e.g. do you often need to write things like:
> 
> start.step(end + 1, increment){| i | block }  
> start.step(end - 1, increment){| i | block }
> 
> Writing in Python, I almost never need to "shift the fence-posts", so to  
> speak. E.g. I virtually never need to write something like:
> 
> range(start, end+1)
> 
> to avoid an off-by-one error. When I used to program in Pascal (which  
> exclusively uses closed intervals) I used to need to do it all the time.  
> What's the Ruby experience?

in my experience open intervals, in c, fortran, c++ and idl often lead to off by one errors but, that being said, i think it's less in fortran because it uses '1' based arrays. also, anyone whose has coded C has probably found 'off, length' to be less error prone and open intervals lend themselves more easily to that notion.

cheers.

a @ [http://codeforpeople.com/](http://codeforpeople.com/)

> **···**
>
> On Oct 24, 2007, at 7:45 PM, Steven D'Aprano wrote:  
> --  
> we can deny everything, except that we have the possibility of being better. simply reflect on that.  
> h.h. the 14th dalai lama

---

<div class="post-metadata">

**Author:** ![Giles\_Bowkett](https://avatars.discourse-cdn.com/v4/letter/g/96bed5/32.png) [@Giles\_Bowkett](https://rubytalk.org/u/Giles_Bowkett)\
**Post date:** [25 October 2007 05:43 UTC](https://rubytalk.org/t/intervals-in-ruby/41651/12 "2007-10-25T05:43:57Z")

</div>

> \> My question is: how useful are all these different mechanisms? Do you  
> \> find that having two operators .. and ... is a blessing, or a curse  
> \> because you can never remember which is which?
> 
> I had a look through about 25,000 lines of Ruby I working with now.
> 
> I've never used ..., only .. -- and then only for choosing parts of  
> an array.

I used ... last week a couple times, for what that's worth.

> In my installed gems (about 60k lines but there are multiple versions  
> of some libraries) this seems to happen in 6 files dealing with  
> bigdecimals, telnet, http, webrick (a web server), and in an xml  
> parser. The most interesting use is in a case statement handling HTTP  
> error codes.

> \> e.g. do you often need to write things like:  
> \>  
> \> start.step(end + 1, increment){| i | block }  
> \> start.step(end - 1, increment){| i | block }
> 
> This does not appear in my code base. I habitually iterate over  
> collections and arrays. I can't recall ever needing the a sequence of  
> integers (except in benchmarks and tests)

Honestly, I think I \*might\* have seen #step before once, in a book.  
I've definitely never seen it in production code that I can recall,  
and I've definitely never used it myself. The idiom of iterating over  
collections became very natural to me very quickly and I think it's  
likely that this is the case for other Ruby programmers in general.

I don't know if this is an important part of programming in Python or  
not. I've played with Python but everything like that, I think I did  
with "for x in y" loops. (those were cool, by the way.) I did do a few  
"for x in range(y)" loops, so I could see how it would matter.

in Ruby it's nearly \*\*always\*\*

collection.each {|foo| bar}

Even when you're dealing with a subset of the collection, or dealing  
with the collection in subsets of X number, it's more like

collection.each { |foo| in\_groups\_of(bar) { baz }}

There's more than one way to do it, like in Perl, but in practice  
people seem to gravitate to this particular way, to the exclusion of  
other ways.

(By the way the syntax is pseudocode.)

> **···**
>
> --  
> Giles Bowkett
> 
> Blog: [http://gilesbowkett.blogspot.com](http://gilesbowkett.blogspot.com)  
> Portfolio: [http://www.gilesgoatboy.org](http://www.gilesgoatboy.org)  
> Tumblelog: [http://giles.tumblr.com/](http://giles.tumblr.com/)

---

<div class="post-metadata">

**Author:** ![Gordon\_Beaton](https://avatars.discourse-cdn.com/v4/letter/g/838e76/32.png) [@Gordon\_Beaton](https://rubytalk.org/u/Gordon_Beaton)\
**Post date:** [25 October 2007 07:00 UTC](https://rubytalk.org/t/intervals-in-ruby/41651/13 "2007-10-25T07:00:03Z")

</div>

For iterating, I agree.

But for case expressions, I prefer the interval to be inclusive.  
Example from the pickaxe book:

&nbsp;&nbsp;kind = case year  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;when 1850..1889 then "Blues"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;when 1890..1909 then "Ragtime"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;when 1910..1929 then "New Orleans Jazz"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;when 1930..1939 then "Swing"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;when 1940..1950 then "Bebop"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else "Jazz"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end

/gordon

> **···**
>
> On Thu, 25 Oct 2007 15:40:00 +0900, Michael Ulm wrote:
> 
> > If there is only one kind of range to be supported (which I  
> > understand to be in sync with the Python philosophy), I agree that  
> > half-open intervals are the way to go.
> 
> --

---

<div class="post-metadata">

**Author:** ![Just\_Another\_Victim1](https://avatars.discourse-cdn.com/v4/letter/j/e56c9b/32.png) [@Just\_Another\_Victim1](https://rubytalk.org/u/Just_Another_Victim1)\
**Post date:** [25 October 2007 07:30 UTC](https://rubytalk.org/t/intervals-in-ruby/41651/14 "2007-10-25T07:30:02Z")

</div>

"Andreas Haller" \<andreashaller@gmail.com\> wrote in message  
news:0C1522C0-3313-4FE0-9846-077D70938EBF@gmail.com...

> > My question is: how useful are all these different mechanisms? Do you  
> > find that having two operators .. and ... is a blessing, or a curse  
> > because you can never remember which is which?
> 
> Hi  
> i think it makes perfect sense to have those two options and with such a  
> similar syntax. I had to think a second everytime to remember which is  
> which, but i got used to it now. (Although it does not make much sense to  
> me that three dots mean "less" than two dots.)

&nbsp;&nbsp;&nbsp;&nbsp;I think of it as the shorter keyword being the one more often used. As  
I'm sure you know, half open intervals are used far more often than closed  
intervals...

&nbsp;&nbsp;&nbsp;&nbsp;It's a little scary that they're so similar but do different things in  
that it may be easy to mistake one for the other. It would be an annoying  
typo bug to track down...

> > [...]. range() always results in a half-open interval:  
> > range(1, 5) =\> 1, 2, 3, 4
> 
> I had to look up the terms "half-open" and "half-closed". http://  
> en.wikipedia.org/wiki/Interval\_(mathematics) says that an half-open  
> interval (2,4] excludes 2, but includes 4. So in Python that would be  
> half-closed intervals by default (right?), ikewise in Ruby.

&nbsp;&nbsp;&nbsp;&nbsp;I don't think that it would be half open, by default, in Python. More  
like it will always be half open in Python.

> What i find strage about ranges is that:  
> (0..3).to\_a # =\> [0, 1, 2, 3]  
> but  
> (3..0).to\_a # =\>

&nbsp;&nbsp;&nbsp;&nbsp;I find this strange, as well...  
&nbsp;&nbsp;&nbsp;&nbsp;Aside from breaking many lines of code, how bad would it be to change  
it?

---

<div class="post-metadata">

**Author:** ![James\_Edward\_Gray\_II](https://avatars.discourse-cdn.com/v4/letter/j/ea5d25/32.png) [@James\_Edward\_Gray\_II](https://rubytalk.org/u/James_Edward_Gray_II)\
**Post date:** [25 October 2007 12:02 UTC](https://rubytalk.org/t/intervals-in-ruby/41651/15 "2007-10-25T12:02:35Z")

</div>

> Both range versions come in handy, for example, if you need to iterate through an array using an index counter then the triple dot is convenient because you do not need to to math:
> 
> for i in 0...ar.size  
> &nbsp;&nbsp;puts ar[i]  
> end
> 
> #times is an alternative here
> 
> ar.size.times do |i|  
> &nbsp;&nbsp;puts ar[i]  
> end

\>\> letters = (0..9).map { |i| (?a + i).chr }  
=\> ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"]  
\>\> letters.each\_index do |i|  
?\> puts letters[i]  
\>\> end  
a  
b  
c  
d  
e  
f  
g  
h  
i  
j  
=\> ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"]

James Edward Gray II

> **···**
>
> On Oct 25, 2007, at 1:40 AM, Robert Klemme wrote:

---

<div class="post-metadata">

**Author:** ![James\_Britt](https://avatars.discourse-cdn.com/v4/letter/j/22d042/32.png) [@James\_Britt](https://rubytalk.org/u/James_Britt)\
**Post date:** [25 October 2007 14:38 UTC](https://rubytalk.org/t/intervals-in-ruby/41651/16 "2007-10-25T14:38:05Z")

</div>

If there is one thing Ruby gets right over every other language it's iteration/looping mechanisms.  
they look strange at first, but use them a bit and the feel natural

> **···**
>
> On Oct 25, 2007, at 5:00 AM, Steven D'Aprano wrote:
> 
> > On Thu, 25 Oct 2007 01:43:33 +0000, Steven D'Aprano wrote:
> > 
> > > I understand that in Ruby you have quite a few choices, some of which  
> > > are half-open like Python, some of which are closed:
> > 
> > ...
> > 
> > > My question is: how useful are all these different mechanisms? Do you  
> > > find that having two operators .. and ... is a blessing, or a curse  
> > > because you can never remember which is which?
> > > 
> > > How useful are the closed interval forms? Do you find yourself making  
> > > off- by-one errors or needing to increment/decrement variables by one?
> > 
> > Thank you for everyone who wrote back, all good food for thought.
> > 
> > Are there many (any?) good examples of where you need to iterate over an  
> > integer count, rather than directly over a data structure?
> > 
> > --  
> > Steven

---

<div class="post-metadata">

**Author:** ![Giles\_Bowkett](https://avatars.discourse-cdn.com/v4/letter/g/96bed5/32.png) [@Giles\_Bowkett](https://rubytalk.org/u/Giles_Bowkett)\
**Post date:** [25 October 2007 17:18 UTC](https://rubytalk.org/t/intervals-in-ruby/41651/17 "2007-10-25T17:18:10Z")

</div>

> Are there many (any?) good examples of where you need to iterate over an  
> integer count, rather than directly over a data structure?

Fizzbuzz. Anything where the problem space involves integers. Ruby  
collection iterating becomes very normal to you when you use it. Any  
problem space which doesn't involve integers and does involve  
collections you'll probably address with collections.

Also, strictly speaking, when you iterate over a collection, you're  
interacting with the collection in an OO manner, while using integer  
indices to access their contents sequentially probably violates the  
Law of Demeter or something. I want to avoid flame wars, especially  
since if there was a flame war about that, it'd be Ruby & Smalltalk  
vs. the universe, but the point seems valid. Getting into  
implementation instead of just telling the object "do this, I don't  
care how."

> **···**
>
> --  
> Giles Bowkett
> 
> Blog: [http://gilesbowkett.blogspot.com](http://gilesbowkett.blogspot.com)  
> Portfolio: [http://www.gilesgoatboy.org](http://www.gilesgoatboy.org)  
> Tumblelog: [http://giles.tumblr.com/](http://giles.tumblr.com/)

---

<div class="post-metadata">

**Author:** ![a11](https://yyz1.discourse-cdn.com/flex029/user_avatar/rubytalk.org/a11/32/8169_2.png) [@a11](https://rubytalk.org/u/a11)\
**Post date:** [25 October 2007 20:48 UTC](https://rubytalk.org/t/intervals-in-ruby/41651/18 "2007-10-25T20:48:05Z")

</div>

yes. the most obvious one is needing adjacent entries and/or self-modification. something along the lines of

pixels.size.times do |i|  
&nbsp;&nbsp;&nbsp;pixel = pixels[i]  
&nbsp;&nbsp;&nbsp;left = pixels[i - 1]  
&nbsp;&nbsp;&nbsp;right = pixels[i + 1]

&nbsp;&nbsp;&nbsp;if left.nil? and condition(right) or  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;condition(left) and condition(right) or  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;condition(left) and right.nil?

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pixel = transformation left, pixel, right  
&nbsp;&nbsp;&nbsp;end  
end

granted, i personally would create my own neighborhood iterator for such a case - but then sometimes you need to compare adjacent neighborhoods...

i would go so far as to say \*any\* interesting algorithm can require random access into a data structure that's also being modified. in those cases iterating by size is a smart alternative since very few data structures in ruby support modification + traversal.

another good use case is

min = [a.size, b.size].min

min.times do |i|  
&nbsp;&nbsp;&nbsp;something\_with a[i] and b[i]  
end

which is to say iterating datasets in parallel.

yes there is zip - fantastic if you are into duplicating both datasets in memory \*and\* are iterating over n=2 data structures but otherwise useless.

that said - i'll take #each or #map any day.

cheers.

a @ [http://codeforpeople.com/](http://codeforpeople.com/)

> **···**
>
> On Oct 25, 2007, at 4:00 AM, Steven D'Aprano wrote:
> 
> > Are there many (any?) good examples of where you need to iterate over an  
> > integer count, rather than directly over a data structure?
> 
> --  
> we can deny everything, except that we have the possibility of being better. simply reflect on that.  
> h.h. the 14th dalai lama

---

<div class="post-metadata">

**Author:** ![Giles\_Bowkett](https://avatars.discourse-cdn.com/v4/letter/g/96bed5/32.png) [@Giles\_Bowkett](https://rubytalk.org/u/Giles_Bowkett)\
**Post date:** [25 October 2007 05:45 UTC](https://rubytalk.org/t/intervals-in-ruby/41651/19 "2007-10-25T05:45:34Z")

</div>

hey, cool. Ruby has "for x in y" too. I had forgotten about that.

> **···**
>
> --  
> Giles Bowkett
> 
> Blog: [http://gilesbowkett.blogspot.com](http://gilesbowkett.blogspot.com)  
> Portfolio: [http://www.gilesgoatboy.org](http://www.gilesgoatboy.org)  
> Tumblelog: [http://giles.tumblr.com/](http://giles.tumblr.com/)

---

<div class="post-metadata">

**Author:** ![Joel\_VanderWerf1](https://avatars.discourse-cdn.com/v4/letter/j/94ad74/32.png) [@Joel\_VanderWerf1](https://rubytalk.org/u/Joel_VanderWerf1)\
**Post date:** [25 October 2007 17:28 UTC](https://rubytalk.org/t/intervals-in-ruby/41651/20 "2007-10-25T17:28:54Z")

</div>

James Edward Gray II wrote:

> **···**
>
> > On Oct 25, 2007, at 1:40 AM, Robert Klemme wrote:
> > 
> > > Both range versions come in handy, for example, if you need to iterate through an array using an index counter then the triple dot is convenient because you do not need to to math:
> > > 
> > > for i in 0...ar.size  
> > > &nbsp;&nbsp;puts ar[i]  
> > > end
> > > 
> > > #times is an alternative here
> > > 
> > > ar.size.times do |i|  
> > > &nbsp;&nbsp;puts ar[i]  
> > > end
> > 
> > \>\> letters = (0..9).map { |i| (?a + i).chr }  
> > =\> ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"]  
> > \>\> letters.each\_index do |i|  
> > ?\> puts letters[i]  
> > \>\> end  
> > a  
> > b  
> > c  
> > d  
> > e  
> > f  
> > g  
> > h  
> > i  
> > j  
> > =\> ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"]
> 
> What was that example meant to show? Must be something other than this:
> 
> puts ("a".."j").to\_a
> 
> --  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

[Next page](https://rubytalk.org/t/intervals-in-ruby/41651.md?page=2)
