Hi --

On Thu, 25 Oct 2007, 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?

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

   items.each_with_index do |item,index|
     puts "Item #{index + 1}: #{item.description}"
   end

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


David

-- 
Upcoming training by David A. Black/Ruby Power and Light, LLC:
   * Advancing With Rails, Edison, NJ, November 6-9
   * Advancing With Rails, Berlin, Germany, November 19-22
   * Intro to Rails, London, UK, December 3-6 (by Skills Matter)
See http://www.rubypal.com for details!