Could you give a real-world example of how it proved useful?
Eg, quoting the text:
> Angelico noted that he has used the Pike programming language, which does have a labeled break. He found that he had used the feature twice in all of the Pike code he has written. Neither of the uses was particularly compelling in his opinion; one was in a quick-and-dirty script and the other is in need of refactoring if he were still working on that project, he said. That was essentially all of the real-world code that appeared in the discussion.
// Wait for our TCP stream to connect
'outer: loop {
poll.poll(&mut events, None).unwrap();
for event in events.iter() {
if event.token() == Token(1) && event.is_writable() {
break 'outer;
}
}
}
though it can be replaced with a helper-function (note: I don't fully know what the code is doing, but the following looks right):
def find_writable_event(events):
for event in events:
if event.token() == Token(1) and event.is_writable():
return True
while 1:
poll.poll(events, None)
if find_writable_event(events):
break
So while there's likely a good real-world example of something which can't easily be re-written in an alternative form for Python, simply pointing to a grep result isn't all that persuasive.
Sure, but I don't think you can really evaluate a feature based on how many times one developer uses them. Nor even on how many times they are used in total.
There are a ton of Python features (and misfeatures) that I'm sure most Python devs never use. __subclasses__ for example, or sitecustomize.py.
Similarly I'm pretty sure Rust's i128 is almost never used but it would be really weird to omit it.
What they can evaluate is that no one has yet come up with a real-world example where it's a useful addition to Python, and at least some of those people involved in the discussion have experience with multi-level break from other languages.
Hence my "Could you give a real-world example of how it proved useful?"
Convincing examples might change their minds!
While simply saying "here's how to find Rust programs which use that construct" is not informative nor convincing.
With __subclasses__ there are definite real-world examples where they are useful. We can see the motivation in the commit history:
commit 1c45073aba8f4097b4dc74d4fd3b2f5ed5e5ea9b
Author: Guido van Rossum <guido@python.org>
Date: Mon Oct 8 15:18:27 2001 +0000
Keep track of a type's subclasses (subtypes), in tp_subclasses, which
is a list of weak references to types (new-style classes). Make this
accessible to Python as the function __subclasses__ which returns a
list of types -- we don't want Python programmers to be able to
manipulate the raw list.
In order to make this possible, I also had to add weak reference
support to type objects.
This will eventually be used together with a trap on attribute
assignment for dynamic classes for a major speed-up without losing the
dynamic properties of types: when a __foo__ method is added to a
class, the class and all its subclasses will get an appropriate tp_foo
slot function.
and the commit logs show an example of use:
Author: Victor Stinner <victor.stinner@gmail.com>
Date: Fri Mar 25 17:36:33 2016 +0100
...
* Use __subclasses__() to get resource classes instead of using an hardcoded
list (2 shutil resources were missinged in the list!)
...
In addition, we can find third-party packages which use it.
I've never used 128-bit integers, but its seems many people do have real-world cases for it.
What do you think is a convincing real-world example that should motivate its inclusion in Python?
> What do you think is a convincing real-world example that should motivate its inclusion in Python?
That Rust example is a decent one. Also the various "find something in a nested structure" examples people have posted.
(And the fact that you can achieve the same result in a more awkward way by putting it in a function and using `return` is irrelevant because there are many many language features that are just convenient sugar: +=, lambdas, even while loops!)
The use of a helper-function is given in the lwn article as a reason for not supporting multi-level break:
] The solution to "Python needs a way to jump out of a chunk of code" is usually to put the chunk of code into a function, then return out of it.
More specifically:
] To make this proposal convincing, we need a realistic example of an algorithm that uses it, and that example needs to be significantly more readable and maintainable than the refactorings into functions, or the use of try…except (also a localised goto).
] If you intend to continue to push this idea, I strongly suggest you look at prior art: find languages which have added this capability, and see why they added it.
The multi-level break in that Rust example may be "more readable and maintainable than the refactorings into functions", but it is not "significantly more readable."
Frankly that's just broken logic. You could easily say:
> The solution to "Python needs a way to increment variables" is usually to so `a = a + 1`.
> To make this proposal convincing, we need a realistic example of an algorithm that uses it, and that example needs to be significantly more readable and maintainable than `a = a + 1`.
Why does `+=` get into the language but labelled breaks (a reasonably standard feature) don't. This isn't hypothetical - not all languages have +=. Matlab for example requires you to do `a = a + 1`.
> The idea behind augmented assignment in Python is that it isn’t just an easier way to write the common practice of storing the result of a binary operation in its left-hand operand, but also a way for the left-hand operand in question to know that it should operate on itself, rather than creating a modified copy of itself.
Here's an example of how "a += b" is not syntactic sugar for "a = a + b". First, "a = a + b", which rebinds 'a' to a new object while leaving 'b' bound to the original:
>>> a = b = [9,8]
>>> a + b
[9, 8, 9, 8]
>>> a = a + b
>>> a
[9, 8, 9, 8]
>>> b
[9, 8]
Second, "a += b", which keeps both a and b bound to the same object:
>>> a = b = [9,8]
>>> a += b
>>> a
[9, 8, 9, 8]
>>> b
[9, 8, 9, 8]
For a more convincing use, consider NumPy arrays, where a+=1 re-use the same (potentially very large) array, while a=a+1 creates a new array.
import numpy
a = b = numpy.array([[1,2], [3, 9]])
a += 1 # modify in-place
a = a + 1 # create a new array
>>> a
array([[ 3, 4],
[ 5, 11]])
>>> b
array([[ 2, 3],
[ 4, 10]])
In-place modification can improve performance over using intermediate/temporary arrays.
Eg, quoting the text:
> Angelico noted that he has used the Pike programming language, which does have a labeled break. He found that he had used the feature twice in all of the Pike code he has written. Neither of the uses was particularly compelling in his opinion; one was in a quick-and-dirty script and the other is in need of refactoring if he were still working on that project, he said. That was essentially all of the real-world code that appeared in the discussion.