[Python-ideas] [Python-Dev] Inclusive Range

Nick Coghlan ncoghlan at gmail.com
Mon Oct 4 14:59:51 CEST 2010

On Mon, Oct 4, 2010 at 5:27 PM, Xavier Morel <python-dev at masklinn.net> wrote:
> Same as the others:
> 0. This is a discussion for python-ideas, I'm CCing that list
> 1. This is a major backwards compatibility breakage, and one which is entirely silent (`print` from keyword to function wasn't)
> 2. It loses not only well-known behavior but interesting properties as well (`range(n)` has exactly `n` elements. With your proposal, it has ``n+1`` breaking ``for i in range(5)`` to iterate 5 times as well as ``for i in range(len(collection))`` for cases where e.g. ``enumerate`` is not good enough or too slow)
> 3. As well as the relation between range and slices
> 4. I fail to see how it is more intuitive (let alone more practical, see previous points)
> 5. If you want an inclusive range, I'd recommend proposing a flag on `range` (e.g. ``inclusive=True``) rather than such a drastic breakage of ``range``'s behavior. That, at least, might have a chance. Changing the existing default behavior of range most definitely doesn't.

A flag doesn't have any chance either - you spell inclusive ranges by
including a "+1" on the stop value.

Closed ranges actually do superficially appear more intuitive
(especially to new programmers) because we often use inclusive ranges
in ordinary speech ("10-15 people" allows 15 people, "ages 8-12"
includes 12 year olds, "from A-Z" includes items starting with "Z").
However, there are some cases where we naturally use half-open ranges
as well (such as "between 10 and 12" excluding 12:01 to 12:59) or
explicitly invoke exclusive ranges as being easier to deal with (such
as the "under 13s", "under 19s", etc naming schemes used for age
brackets in junior sports)

However, as soon you move into the mathematical world (including
programming), closed ranges turn out to require constant adjustments
in the arithmetic, so it far more natural to use half-open ranges

Xavier noted the two most important properties of half-closed ranges
for Python: they match the definition of subtraction, such that
len(range(start, stop)) =  (stop - start), and they match the
definition of slicing as being half-open.

As to whether slicing itself being half-open is beneficial, the value
of that becomes clear ones you start trying to manipulate ranges:
With half-open slices, the following is true: s == s[:i] + s[i:]
With inclusive slices (which would be needed to complement inclusive
range), you would need either a -1 on the stop value of the first
slice, or a +1 on the start value of the second slice.
Similarly, if you know the length of the slice you want, then you can
grab it via s[i:i+slice_len], while you'd need a -1 correction on the
stop value if slices were inclusive.

There are other benefits to half-open ranges when it comes to
(approximately) continuous spectra like time values, floating point
numbers and lexically ordered strings. Being able to say things like
"10:00" <= x < '12:00", 10.0 <= x < 12.0, "a" <= x < "n" are much
clearer than trying to specify their closed range equivalents. While
that isn't specifically applicable to the range() builtin, it is
another factor in why it is important to drink the "half-open ranges
are your friend" Kool-aid as a serious programmer.


P.S. many of the points above are just rephrased from
http://www.siliconbrain.com/ranges.htm, which is the first hit when
Googling "half-open ranges"

Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia

More information about the Python-ideas mailing list