Re: range() (fwd)

Lou Kates (louk@research.teleride.on.ca)
Mon, 29 Jun 92 21:33:11 EDT

Forwarded message:
> Sender: Guido.van.Rossum@cwi.nl
>
> >In Python, you currently have to say:
> >
> > for i in range(len(a)-1,-1,-1):
> >
> >to iterate backwards over the indices of a list. Range should be
> >defined so that you can simply say:
> >
> > for i in range(len(a),0,-1):
> >
> >If k>0, this could be done by defining
> >
> > range(m,n,-k)
> >
> >to be equivalent to
> >
> > range(n,m,k).reverse()
> >
> >That is to say, if the third argument is negative then the range
> >that is produced includes the second argument but not the first.
> >If the third argument is positive the range includes the first
> >argument but not the second as is currently the case.
>
> Interesting suggestion; at first I thought I'd agree with you
> completely (barring backward compatibility, which I don't think will
> be a big problem); but what about things like range(0, -5, -1)?
> Currently this returns [0, -1, -2, -3, -4]; under Lou's proposed
> definition it would change to [-1, -2, -3, -4, -5]. Intimate lovers
> of two's complement arithmetic might expect that, but to me it feels
> slightly uneasy.
>
> Any other opinions?
>
> --Guido van Rossum, CWI, Amsterdam <guido@cwi.nl>
> "This is an ex-parrot"
>

You make an interesting point. I would like to expand on it.
Suppose s is scalar and v is a list regarded as a vector. As in
usual vector arithmetic define s * v to be the list, i.e. vector,
whose i-th element is s * v[i].

Then the existing range() function in Python enjoys the following
pleasing proportionality property:

s * range(m, n, k) = range(s * m, s * n, s * k)

for all non-zero values of s including negative values.

The definition that I had proposed is the same as the existing
range() for positive steps and by definition obeys the following
identity which allows it to be extended to negative steps:

range(m, n, -k) = range(n, m, k).reverse()

With the existing range(), the formula for s * range() as a
range() is simple even if s<0 but the formula for
range().reverse() as a range() is complex.

In my proposed formula, the formula for range().reverse() as a
range() is simple but the formula for s * range() as a range is
complex if s<0.

Its a judgement call as to whether range() should behave nicely
under proportionality or reversal since it appears that it won't
behave nicely under both.

I have to admit that I prefer the proportionality identity which
means that range() would stay as it is.

Getting back to the original example, I guess the moral of the
story is that if one wants to elegantly express backwards
iteration over list indices one should use the idiom:

for i in range(len(a)).reverse():

Lou

P.S. Note how the above discussion required APL-like vector
multiplication to state the proportionality property even in
this apparently not heavily mathematical setting!

-- 
Lou Kates, louk@research.teleride.on.ca