Special keyword denoting an infinite loop
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. For instance while True:
do_something() do_something_else()
would turn to loop:
do_something() do_something_else()
On Sat, Jun 28, 2014 at 01:04:24AM -0700, Thomas Allen wrote:
Rust language defines a special way to make an infinite loop ( http://doc.rust-lang.org/tutorial.html#loops).
Do they give an explanation for why they use a keyword for such a redundant purpose?
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 understand that *infinite loops* themselves are useful, and that recursion can be replaced by iteration, but how does the "loop" keyword solve these issues better than "while True"?
I personally find it much prettier than *while True* or *while 1*.
If the only advantage of this is that you personally find it prettier, then I'm a strong -1 on this suggestion. * I personally find it less elegant than "while True". "while True" tells you explicity what it does: it's a while loop, and it operates while True is true (i.e. forever). "loop" looks like an incomplete line: what sort of loop, while, repeat or for? Loop for how long? It's all implicit. * It's yet another special keyword to memorise. It doesn't eliminate the need to know "while", or to know "True", and it gives you no extra benefit. It's just completely redundant. Suppose "loop" becomes a keyword in Python 3.5. That means that every existing Python program that uses "loop" as a function or variable cannot work in Python 3.5. It also means that any Python 3.5 code that uses the "loop" keyword Adding new keywords is only done for the most critical reasons, or when there is no other good alternative, not just on a whim. There is already a perfectly good way to write infinite loops, adding the "loop" keyword doesn't add anything to the language, it just breaks working code for the sake of a minor, cosmetic change.
It won't cause any problems with existing programs, because *loop* is very rarely used as a variable name.
How do you know it is rare? I've written code where loop is a name: def main(): setup() loop() -- Steven
Steven D'Aprano, 28.06.2014 11:11:
On Sat, Jun 28, 2014 at 01:04:24AM -0700, Thomas Allen wrote:
It won't cause any problems with existing programs, because *loop* is very rarely used as a variable name.
How do you know it is rare? I've written code where loop is a name:
def main(): setup() loop()
Also, this example only uses English names. There is no reason to assume that programmers with other native languages that (also) use ASCII letters or transliterations would not happen to have a word spelled "loop" in their language that they may commonly use in their programs. Or that programmers with a lower level of proficiency in the English language would also not consider "loop" a good name for a variable or function. Or that there is no technical/business/science/social/you-name-it terminology whatsoever that makes "loop" appear as the most obvious choice for a name in a program of that domain. "Obvious Reasoning" easily fails when it comes to understanding naming decisions, especially across cultural boundaries. Adding a new keyword needs very serious reasoning, and that's a good thing. Stefan
On Sat, Jun 28, 2014, at 06:05, Stefan Behnel wrote:
Adding a new keyword needs very serious reasoning, and that's a good thing.
For pedantry's sake, I will note that "NAME ':'" is not a valid sequence to start a statement with today. That is, however, probably _not_ a road anyone wants to go down if there is any other option. It's almost enough to make one wish that Python had defined an expansive set of reserved words as Javascript does - a set which might not contain "loop" but would probably contain "do". What about _just_ "while:" or "for:"?
On Mon, Jun 30, 2014 at 01:24:37PM -0400, random832@fastmail.us wrote:
On Sat, Jun 28, 2014, at 06:05, Stefan Behnel wrote:
Adding a new keyword needs very serious reasoning, and that's a good thing. [...] What about _just_ "while:" or "for:"?
Why bother? Is there anything you can do with a bare "while:" that you can't do with "while True:"? If not, what's the point? -- Steven
On 06/30/2014 01:20 PM, Steven D'Aprano wrote:
On Mon, Jun 30, 2014 at 01:24:37PM -0400, random832@fastmail.us wrote:
On Sat, Jun 28, 2014, at 06:05, Stefan Behnel wrote:
Adding a new keyword needs very serious reasoning, and that's a good thing. [...] What about _just_ "while:" or "for:"?
Why bother? Is there anything you can do with a bare "while:" that you can't do with "while True:"? If not, what's the point?
It looks like (in python3) "while 1:", "while True:", and while with a string, generates the same byte code. Just a bare SETUP_LOOP. Which would be the exact same as "while:" would. So no, it wouldn't make a bit of difference other than saving a few key strokes in the source code.
def L(): ... while True: ... break ... L() dis(L) 2 0 SETUP_LOOP 4 (to 7)
3 >> 3 BREAK_LOOP 4 JUMP_ABSOLUTE 3 >> 7 LOAD_CONST 0 (None) 10 RETURN_VALUE
def LL(): ... while 1: ... break ... dis(LL) 2 0 SETUP_LOOP 4 (to 7)
3 >> 3 BREAK_LOOP 4 JUMP_ABSOLUTE 3 >> 7 LOAD_CONST 0 (None) 10 RETURN_VALUE
def LLL(): ... while "looping": ... break ... dis(LLL) 2 0 SETUP_LOOP 4 (to 7)
3 >> 3 BREAK_LOOP 4 JUMP_ABSOLUTE 3 >> 7 LOAD_CONST 0 (None) 10 RETURN_VALUE Cheers, Ron
On Sat, Jun 28, 2014 at 2:11 AM, Steven D'Aprano <steve@pearwood.info> wrote:
On Sat, Jun 28, 2014 at 01:04:24AM -0700, Thomas Allen wrote:
Rust language defines a special way to make an infinite loop ( http://doc.rust-lang.org/tutorial.html#loops).
Do they give an explanation for why they use a keyword for such a redundant purpose?
Sure. "while true {...}" would require magic by the compiler to make it optimized and to make things like the following pass compile-time checks: "let a; while true { a = 1; break;}; return a". With a while loop, Rust can't really know that the loop executes even once without special-casing the argument, so it emits a compile-time error because the variable a might be uninitialized. If Rust magically knew about while true, then it becomes confusing if replacing "true" with something the compiler doesn't directly understand causes the compiler to get confused. Special cases aren't special enough to break the rules, so Rust decides that the special case here deserves its own keyword. In Python, there is no special case at all, so there is no extra keyword. As it should be. Rust has some ideas Python could borrow, but this ain't one of them. -1. -- Devin
On 28 June 2014 22:53, Devin Jeanpierre <jeanpierreda@gmail.com> wrote:
On Sat, Jun 28, 2014 at 2:11 AM, Steven D'Aprano <steve@pearwood.info> wrote:
On Sat, Jun 28, 2014 at 01:04:24AM -0700, Thomas Allen wrote:
Rust language defines a special way to make an infinite loop ( http://doc.rust-lang.org/tutorial.html#loops).
Do they give an explanation for why they use a keyword for such a redundant purpose?
Sure. "while true {...}" would require magic by the compiler to make it optimized and to make things like the following pass compile-time checks: "let a; while true { a = 1; break;}; return a". With a while loop, Rust can't really know that the loop executes even once without special-casing the argument, so it emits a compile-time error because the variable a might be uninitialized. If Rust magically knew about while true, then it becomes confusing if replacing "true" with something the compiler doesn't directly understand causes the compiler to get confused.
Special cases aren't special enough to break the rules, so Rust decides that the special case here deserves its own keyword.
Ah, that makes a lot of sense - I forgot that it wouldn't be just an optimisation for Rust, but a control flow validity checking change as well. Thanks for the explanation. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia
On Sat, Jun 28, 2014 at 6:04 PM, Thomas Allen <jsbfox@gmail.com> wrote:
I personally find it much prettier than while True or while 1.
One common technique I've seen is the self-documenting infinite loop: while "more work to be done": get_work() do_work() If you're worried about the prettiness of "while True", this might help. Since any non-empty string counts as true, this can add a bit more information without disrupting the loop itself. ChrisA
On 28 June 2014 18:04, Thomas Allen <jsbfox@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@gmail.com | Brisbane, Australia
On 28/06/2014 09:04, Thomas Allen 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.
For instance
while True: do_something() do_something_else()
would turn to
loop: do_something() do_something_else()
No thank you, my standard answer applies. I prefer Python in a Nutshell to fit in my pocket, not the back of a 40 ton articulated lorry. -- My fellow Pythonistas, ask not what our language can do for you, ask what you can do for our language. Mark Lawrence --- This email is free from viruses and malware because avast! Antivirus protection is active. http://www.avast.com
participants (9)
-
Chris Angelico
-
Devin Jeanpierre
-
Mark Lawrence
-
Nick Coghlan
-
random832@fastmail.us
-
Ron Adam
-
Stefan Behnel
-
Steven D'Aprano
-
Thomas Allen