Re: Non-list ranges

Tim Peters (tim@ksr.com)
Tue, 26 Oct 93 00:15:36 -0400

> > [tim, whining that 'range' should be special-cased in 'for', by any
> > dirty trick that works]
> > [how about at runtime via a context-sensitive trick?]
> [guido]
> Hmm, I suppose the compiler could recognize the range() call and
> generate an instruction to set a hint flag that would be picked up by
> the built-in range(). Will think about it some more...

If that's doable, I like it! I don't understand the implementation well
enough to be helpful. As a user, I whine that range makes perfect sense
the way it is already, and just needs to be trickier "somehow" in the one
context where its existing semantics are correct but overbearingly
inefficient.

> > If this is the way to do it, I'd rather that range be left alone & a new
> > builtin introduced. Think of all the Sieve of Eratosthenes programs
> > you'll break otherwise <wink>.
>
> Really? Actually the only non-for-loop use of range() I can imagine
> is your "enumerated values" trick:
>
> [red, green, blue] = range(3)

Drat -- I was so relieved when you first attributed this kludgexxxxxx
fine technique to Majewski <wink>. Here's a prime sieve program I pass
around here for pedagogical purposes; note that it uses "range" in 3
distinct ways, only one of which is clearly optimizable:

def siv( n ): # return list of primes, in order, <= n
if n <= 3:
return range(2,n+1)

if n & 1:
n = n + 1

primes = range(3,n,2)
primes.insert(0,2)

i = 1
p = primes[i]
sq = p*p
while sq <= n:
for x in range( sq, n, 2*p ):
if x in primes:
primes.remove(x)
i = i + 1
p = primes[i]
sq = p * p

return primes

Of course there are quicker ways to write the venerable sieve in Python,
but this way is clean and people have found it instructive. God only
knows how many have adopoted similar uses for range.

range-used-to-return-an-arithmetic-sequence-as-a-list is also useful for
the same reasons APL's iota function, and the Emac's calculator Calc's
function calc-index (both of which do much the same thing), are useful.
That's in support of a style of interactive computation that's not built
in to Python, but very easy to do in Python given a handful of helper
functions (like the 'map' and 'func' examples from a different thread).

You can also find non-'for' examples of 'range' in the library you
distribute <wink>:

auds.py: list = range(RATE)
calendar.py: r7 = range(7)
dis.py:opname = range(256)

Certainly the 'for' use is overwhelmingly most common, though.

> > Or perhaps range could return an object of this new non-storing type, and
> > that also magically transforms itself into a vanilla list if used in a
> > context that requires a genuine list ...
> [type() creates a problem]

I agree that's a problem, and will refrain from suggesting a kludge in
the type system too to worm around it.

My view is that range semantics are fine as-is, and speeding things up in
the 'for' context is simply a matter of translator optimization (& being
in the optimization biz myself, there is no limit to the sickness I'll
introduce behind the scenes to make a pleasant abstraction appear
healthy).

If you'd rather make range magical in a new & incompatible way, I can
live with that too.

Question: In the absence of a
from something import *

statement, are there other cases where Python cannot (in principle, & at
compile time) tell whether the name 'range' denotes the built-in? This
is the tip of a much broader question, relevant a few years down the
road, when Python has taken over much of the world & I'll be thinking of
making a living by selling an optimizing Python compiler <smile>.

cleanliness-is-next-to-sterility-ly y'rs - tim

Tim Peters tim@ksr.com
not speaking for Kendall Square Research Corp