[Python-ideas] Special keyword denoting an infinite loop

Nick Coghlan ncoghlan at gmail.com
Sat Jun 28 12:24:40 CEST 2014


On 28 June 2014 18:04, Thomas Allen <jsbfox at gmail.com> wrote:
> Rust language defines a special way to make an infinite loop
> (http://doc.rust-lang.org/tutorial.html#loops).
>
> I propose adding the same keyword to Python. It will be very useful for WSGI
> servers and will suit as a more convenient replacement for recursion (hence
> Python doesn't do TRE). I personally find it much prettier than while True
> or while 1. It won't cause any problems with existing programs, because loop
> is very rarely used as a variable name.

"won't cause any problems" does not mesh with an assertion of "very
rarely used" on two counts:

- "very rarely" means it *will* cause problems for at least some programs
- the "very rarely used" assertion isn't backed by any analysis

However, it's a useful example for illustrating some good questions to
ask about any proposals to change the language:

1. What else will have to change as a consequence?
2. Who will be hurt by this change, and how much will they be hurt?
3. Who will gain from this change, and how much will they gain?

I'm going to work through and answer all of these for this proposal -
this isn't to pick on you, it's to show the kind of thinking that may
lie behind a terse "No" or "That's a terrible idea" when a dev is
pressed for time and isn't able to write out their full rationale for
disliking a suggestion :)

Starting from the top:

1. What else will have to change as a consequence?

In this case, a quick search over CPython itself for "loop" variables finds:

- the "asyncore.loop" public API
- parameters named "loop" in the asyncio public API

Really, we can stop there - a new keyword that conflicts with public
APIs in the standard library just won't happen without an
extraordinarily compelling reason, and it's unlikely such a reason is
going to be suddenly discovered for a language that has already been
around for more than 20 years. However, I'll continue on to illustrate
how even a quick check like running "pss --python loop" from a CPython
checkout (which is all I did to come up with these examples) can
recalibrate our intuitions about variable names and the impact of
introducing new keywords.

Additional uses of "loop" as a name in CPython:

- many internal variables named "loop" in asyncio and its test suite
- a call to asyncore.loop in the smtpd standard library module
- a "loop" counter in the hashlib standard library module
- calls to asyncore.loop in the test suite for the asyncore standard
library module
- a call to asyncore.loop in the test suite for the asynchat standard
library module
- a call to asyncore.loop in the test suite for the poplib standard
library module
- a call to asyncore.loop in the test suite for the ftplib standard
library module
- a call to asyncore.loop in the test suite for the logging standard
library module
- a call to asyncore.loop in the test suite for the ssl standard library module
- a call to asyncore.loop in the test suite for the os standard library module
- a "loop" attribute in the test suite for the cyclic garbage collector
- a "loop" variable in the test suite for the faulthandler module
- a "loop" variable in the test suite for the signal module
- a "loop" variable in the ccbench tool (used to check GIL tuning parameters)

In addition to the above cases that actually *do* use "loop", there
are plenty of other cases called things like "_loop", "mainloop" or
"cmdloop", that could easily have been called just "loop" instead. The
"very rarely used" claim doesn't hold up, even just looking at the
standard library. It's a relatively *domain specific* variable name,
but that's not the same as being rare - in the applicable domain, it
gets used a *lot*.

The search shows that "loop" is also used in many comments as a
generic term, and I know from personal experience that is often used
as an umbrella term where saying "loop statement" encompasses both for
loops and while loops.

2. Who will be hurt by this change, and how much will they be hurt?

- anyone affected by the backwards compatibility break for asyncore and asyncio
- anyone with an existing variable called "loop" (which includes the
core dev team)
- anyone used to using "loop statement" as an umbrella term (which includes me)
- anyone tasked with explaining why there's a dedicated alternative
spelling for "while True:" and "while 1:" in a way that students can
grasp easily (the compiler can already detect and optimise them with
their existing spelling, so the keyword isn't needed for that. Even
static analysis tools can pick up the explicit infinite loops pretty
easily. That only leaves the readability argument, which has a certain
amount of merit as described below)

3. Who will gain from this change, and how much will they gain?

- future learners of Python may more easily grasp that "while
True:"/"while 1:" infinite loops tend to serve a fundamentally
different purpose than normal while loops. Unfortunately, Rust chooses
to allow both the "infinite loop" and the normal "while loop" to be
used to implement loop-and-a-half semantics, so it doesn't actually
make that distinction - "loop" is literally just an alternative
spelling of "while true", that provides no additional hints as to
whether or not "break" might be present in the loop body.

For Python, the backwards compatibility issues make the idea of "loop"
as a new keyword a clear loss, and there's insufficient gain in the
idea in general to be worth pursuing it further.

I don't think the referenced feature actually makes much sense as part
of Rust either, but starting afresh means it is at least harmless,
albeit a little redundant. If it disallowed "break", you'd at least
have a clear indicator that "this is the last statement in this
execution unit - the only way out now is to return to our caller".

Regards,
Nick.

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


More information about the Python-ideas mailing list