[Python-Dev] Integer division transition

Guido van Rossum guido@python.org
Sun, 05 Nov 2000 21:34:40 -0500


[Guido]
> > - Integer division.  If we want to play by Paul Prescod's Language
> >   Evolution rules (PEP 5), we better get started on the first stage.
> >   E.g. we could introduce a // operator in 2.1 for integer division,
> >   and issue a warning when / is used for integers.  Then a year later
> >   (i.e., March 2002!) we could change / so that it returns a floating
> >   point number.

[MAL]
> +0... and then only, if there will be a tool to check Python
> source code for integer divides.

Hm.  I don't believe it's possible to write a tool to check for
integer divides by inspection of the source code only -- you have to
actually execute the code (with specific input, etc.).

However, with the right warnings framework in place (I'll post some
ideas about this under a separate subject), the Python interpreter
itself can be the perfect tool to do the checking.  Given that it's
pretty uncontroversial that 1/2 in Py3K should equal 0.5, I'd rather
get this started sooner than later.

Let me state some requirements:

- We don't want to break code in 2.1 that works in 2.0.

- It's okay to issue warnings though (my warnings proposal will limit
  the warnings to once per source line).

- In Py3K, 1/2 will yield 0.5 and users must use a different way to
  spell floor(x/y).

- Starting in 2.1, we want to issue warnings that encourage users to
  make their code Py3K-ready.

- We want (almost) all users to have converted their code to using
  1//2 instead of 1/2 by the time 2.n (the last 2.x version before
  Py3K is released) comes out, because unchanged code will silently
  change its meaning at the Py3K transition.

- Code that is Py3K-ready (in this respect) should trigger no warnings
  in Python 2.1.

Note: it is open for debate whether the result of x/y for integer (or
long integer) arguments should yield an integer (or long integer) in
those cases where the result *is* representable as such (e.g. 4/2).
It is possible that the numeric tower will render this problem moot --
but that depends on what happens to Moshe's PEP 228, and that's a much
longer story.  However, I think we can decide on the transition path
from / to // independent from the outcome of that discussion, since in
all cases it is clear that 1/2 will change in meaning.

Here's a concrete proposal (could be PEPped pretty easily):

- In Py3K, there will be two division operators:

  - x/y will always yield the mathematically expected result (possibly
    inexact, depending on how the numeric model is changed).

  - x//y will always yield the floor of the mathematical result, even
    for float arguments.  For complex arguments, this should raise an
    exception, just as int(1j) does today.

- Starting with Python 2.1, x//y will do the right thing (1//2 == 0).

- In 2.1, using x/y for ints and longs will issue a warning.

- In Py3K, there *might* be a special "backward incompatibility
  warning mode" that issues warnings when x/y is used for ints; 1/2
  will still yield 0.5 in this mode, but a warning will be issued.

This is a minimal proposal.  If Python were to grow a syntax for
pragmas, it would be nice to have a pragma saying "I want int/int to
do float division" in code that is Py3K ready; otherwise, this always
has to be spelled as float(x)/y to ensure proper working in 2.x as
well as in Py3K.

David Scherer proposed to spell this pragma as a "magical import"
(http://www.python.org/pipermail/idle-dev/2000-April/000138.html). This
is an OK idea (+0) because it can be assumed to fail in pre-2.1
installations and doesn't require new syntax.  I don't give it a +1
because it's a hack -- "import" doesn't quite convey the intention.
(Perl's "use" is better for this purpose!)

Tim didn't seem to like this idea much
(http://www.python.org/pipermail/python-dev/2000-April/010029.html).
His dislike seems based on the assumption that such annotations would
mention specific language (or interpreter) version numbers, which
could be interpreted as resisting progress (one moment 1.7 is a
forward looking version, but the next moment it is backward looking).
However if we use directives (I don't want to call them pragmas
because pragmas are supposed to be ignorable) to select specify
specific features, especially features for which there are only two
versions (the old way and the new way) then it seems okay to use such
a mechanism -- if we can agree on a syntax for directives.

Hm, reading Tim's post again it seems he's mostly objecting against
defaulting to an old version.  I have to agree with him there.
However what I'm proposing here is defaulting to the current version,
and allowing a way to select a "future version" as an alternative.

If we don't adopt directives, all we need to do (in Python 2.1) is add
a new opcode for //, keeping the opcode for / unchanged.  If we do
adopt directives, we'll need to introduce two new opcodes: one for the
new (always float) /, one for the new //, still keeping the old /
opcode with the 2.0 meaning.  The latter is what David Scherer
proposes (and what he needs for his students).  Note that it would be
okay to introduce directives in a later 2.x version -- this won't
break any previous code.

--Guido van Rossum (home page: http://www.python.org/~guido/)