Re: Ideas about how software should behave (was: replacing `else` with `then` in `for` and `try`)
On Wed, Nov 8, 2017 at 11:34 AM, Chris Angelico wrote: > On Thu, Nov 9, 2017 at 5:20 AM, Ian Kelly wrote: >> On Wed, Nov 8, 2017 at 11:12 AM, Chris Angelico wrote: >>> Except that "yield from" is used by generators to delegate to other >>> generators, and "await" is used by coroutines to delegate to other >>> coroutines. In an asynchronous generator, "yield" produces values, and >>> "yield from" would delegate to another asynchronous generator. They >>> are NOT synonyms. >> >> Only because the devs have chosen to reserve the possibility of >> asynchronous generators. Abstractly, coroutines and generators are >> distinct concepts, but pragmatically, coroutines *are* generators. >> Native coroutines don't actually change this; they just do a better >> job of hiding it. > > Coroutines *are implemented using* generators. And I don't know what > you mean by "reserve the possibility of"; asynchronous generators do > exist: They didn't exist when native coroutines were implemented. That's when the possibility was reserved. > PEP 525 https://www.python.org/dev/peps/pep-0525/ says: > """ > While it is theoretically possible to implement yield from support for > asynchronous generators, it would require a serious redesign of the > generators implementation. > """ > > In other words, it's only because of *implementation details* that > "yield from" inside a generator is difficult. There's no > language-level reason for it to be forbidden, and there is absolutely > NO correlation between "await" and "yield from" in an async function. Since we're quoting PEPs, here's what PEP 492 says about "await": https://www.python.org/dev/peps/pep-0492/#id56 """ await, similarly to yield from, suspends execution of [the] coroutine until [the] awaitable completes and returns the result data. It uses the yield from implementation with an extra step of validating its argument. await only accepts an awaitable, which can be one of: * A native coroutine object returned from a native coroutine function. * A generator-based coroutine object returned from a function decorated with types.coroutine(). * An object with an __await__ method returning an iterator. Any yield from chain of calls ends with a yield. This is a fundamental mechanism of how Futures are implemented. Since, internally, coroutines are a special kind of generators, every await is suspended by a yield somewhere down the chain of await calls (please refer to PEP 3156 for a detailed explanation). To enable this behavior for coroutines, a new magic method called __await__ is added. In asyncio, for instance, to enable Future objects in await statements, the only change is to add __await__ = __iter__ line to asyncio.Future class. [remainder of section snipped for brevity] """ Points to note: "similarly to yield from"; "uses the yield from implementation"; "internally, coroutines are a special kind of generators"; "every await is suspended by a yield"; "to enable Future objects in await statements, the only change is to add __await__ = __iter__". "await" was designed to be a *drop-in replacement* for "yield from" so your insistence that they're unrelated is kind of mind-boggling. -- https://mail.python.org/mailman/listinfo/python-list
Re: Ideas about how software should behave (was: replacing `else` with `then` in `for` and `try`)
On Thu, Nov 9, 2017 at 5:20 AM, Ian Kelly wrote: > On Wed, Nov 8, 2017 at 11:12 AM, Chris Angelico wrote: >> Except that "yield from" is used by generators to delegate to other >> generators, and "await" is used by coroutines to delegate to other >> coroutines. In an asynchronous generator, "yield" produces values, and >> "yield from" would delegate to another asynchronous generator. They >> are NOT synonyms. > > Only because the devs have chosen to reserve the possibility of > asynchronous generators. Abstractly, coroutines and generators are > distinct concepts, but pragmatically, coroutines *are* generators. > Native coroutines don't actually change this; they just do a better > job of hiding it. Coroutines *are implemented using* generators. And I don't know what you mean by "reserve the possibility of"; asynchronous generators do exist: >>> async def gen(): ... yield 1 ... yield 2 ... yield 3 ... await something ... yield 4 ... >>> gen() PEP 525 https://www.python.org/dev/peps/pep-0525/ says: """ While it is theoretically possible to implement yield from support for asynchronous generators, it would require a serious redesign of the generators implementation. """ In other words, it's only because of *implementation details* that "yield from" inside a generator is difficult. There's no language-level reason for it to be forbidden, and there is absolutely NO correlation between "await" and "yield from" in an async function. ChrisA -- https://mail.python.org/mailman/listinfo/python-list
Re: Ideas about how software should behave (was: replacing `else` with `then` in `for` and `try`)
On Wed, Nov 8, 2017 at 11:12 AM, Chris Angelico wrote: > On Thu, Nov 9, 2017 at 5:05 AM, Ian Kelly wrote: >> On Wed, Nov 8, 2017 at 9:31 AM, Chris Angelico wrote: >>> On Thu, Nov 9, 2017 at 3:19 AM, Ian Kelly wrote: I was not referring to the possible future use of yield from for async generators; I was referring to the possibility *today* of using "yield from" as a synonym for *await*. As far as I know the only major obstacle to that is that the authors (with good reason) made it a SyntaxError. This is exactly the same sort of situation: it's a construct that would otherwise be perfectly valid, but it's made a SyntaxError specifically to prevent users from doing some the devs don't want them to. >>> >>> I don't understand why you would use "yield from" as a synonym for >>> "await". They are not equivalent. Why would you use one in place of >>> the other? >> >> There's not really a good reason to use "yield from" with "async def" >> when you could just use "await", but the point is that in principle >> you could. In a generator-based coroutine (e.g. asyncio prior to >> Python 3.5), "yield from" is used to pause the coroutine and wait on >> some future. In a native coroutine (e.g. after Python 3.5), "await" is >> used to pause the coroutine and wait on some future. The >> implementation AIUI is essentially the same; the __await__ method is >> even required to return an iterator, just like __iter__. >> >> That's why I'm saying that they're basically synonyms. All that's >> really separating them is the syntax error. > > Except that "yield from" is used by generators to delegate to other > generators, and "await" is used by coroutines to delegate to other > coroutines. In an asynchronous generator, "yield" produces values, and > "yield from" would delegate to another asynchronous generator. They > are NOT synonyms. Only because the devs have chosen to reserve the possibility of asynchronous generators. Abstractly, coroutines and generators are distinct concepts, but pragmatically, coroutines *are* generators. Native coroutines don't actually change this; they just do a better job of hiding it. -- https://mail.python.org/mailman/listinfo/python-list
Re: Ideas about how software should behave (was: replacing `else` with `then` in `for` and `try`)
On Thu, Nov 9, 2017 at 5:05 AM, Ian Kelly wrote: > On Wed, Nov 8, 2017 at 9:31 AM, Chris Angelico wrote: >> On Thu, Nov 9, 2017 at 3:19 AM, Ian Kelly wrote: >>> I was not referring to the possible future use of yield from for async >>> generators; I was referring to the possibility *today* of using "yield >>> from" as a synonym for *await*. As far as I know the only major >>> obstacle to that is that the authors (with good reason) made it a >>> SyntaxError. This is exactly the same sort of situation: it's a >>> construct that would otherwise be perfectly valid, but it's made a >>> SyntaxError specifically to prevent users from doing some the devs >>> don't want them to. >> >> I don't understand why you would use "yield from" as a synonym for >> "await". They are not equivalent. Why would you use one in place of >> the other? > > There's not really a good reason to use "yield from" with "async def" > when you could just use "await", but the point is that in principle > you could. In a generator-based coroutine (e.g. asyncio prior to > Python 3.5), "yield from" is used to pause the coroutine and wait on > some future. In a native coroutine (e.g. after Python 3.5), "await" is > used to pause the coroutine and wait on some future. The > implementation AIUI is essentially the same; the __await__ method is > even required to return an iterator, just like __iter__. > > That's why I'm saying that they're basically synonyms. All that's > really separating them is the syntax error. Except that "yield from" is used by generators to delegate to other generators, and "await" is used by coroutines to delegate to other coroutines. In an asynchronous generator, "yield" produces values, and "yield from" would delegate to another asynchronous generator. They are NOT synonyms. ChrisA -- https://mail.python.org/mailman/listinfo/python-list
Re: Ideas about how software should behave (was: replacing `else` with `then` in `for` and `try`)
On Wed, Nov 8, 2017 at 9:31 AM, Chris Angelico wrote: > On Thu, Nov 9, 2017 at 3:19 AM, Ian Kelly wrote: >> I was not referring to the possible future use of yield from for async >> generators; I was referring to the possibility *today* of using "yield >> from" as a synonym for *await*. As far as I know the only major >> obstacle to that is that the authors (with good reason) made it a >> SyntaxError. This is exactly the same sort of situation: it's a >> construct that would otherwise be perfectly valid, but it's made a >> SyntaxError specifically to prevent users from doing some the devs >> don't want them to. > > I don't understand why you would use "yield from" as a synonym for > "await". They are not equivalent. Why would you use one in place of > the other? There's not really a good reason to use "yield from" with "async def" when you could just use "await", but the point is that in principle you could. In a generator-based coroutine (e.g. asyncio prior to Python 3.5), "yield from" is used to pause the coroutine and wait on some future. In a native coroutine (e.g. after Python 3.5), "await" is used to pause the coroutine and wait on some future. The implementation AIUI is essentially the same; the __await__ method is even required to return an iterator, just like __iter__. That's why I'm saying that they're basically synonyms. All that's really separating them is the syntax error. -- https://mail.python.org/mailman/listinfo/python-list
Re: Ideas about how software should behave (was: replacing `else` with `then` in `for` and `try`)
On Thu, Nov 9, 2017 at 3:19 AM, Ian Kelly wrote: > I was not referring to the possible future use of yield from for async > generators; I was referring to the possibility *today* of using "yield > from" as a synonym for *await*. As far as I know the only major > obstacle to that is that the authors (with good reason) made it a > SyntaxError. This is exactly the same sort of situation: it's a > construct that would otherwise be perfectly valid, but it's made a > SyntaxError specifically to prevent users from doing some the devs > don't want them to. I don't understand why you would use "yield from" as a synonym for "await". They are not equivalent. Why would you use one in place of the other? ChrisA -- https://mail.python.org/mailman/listinfo/python-list
Re: Ideas about how software should behave (was: replacing `else` with `then` in `for` and `try`)
On Tue, Nov 7, 2017 at 2:42 PM, Chris Angelico wrote: > On Wed, Nov 8, 2017 at 8:16 AM, Ian Kelly wrote: >>> Not one of these is syntactically invalid. Why should "else without >>> break" be trapped by the parser? Your other examples mostly have good >>> parser-level reasons for being errors >> >> No, they don't. All four of them could just as easily also be accepted >> by the parser and only flagged as linter warnings. > > If everyone in the world agreed that a tab was equal to eight spaces, > then I would agree that the tab/space discrepancy could be considered > a linter warning. But there's no such agreement, which means that > having the language declare some equivalency is extremely dangerous. Really? I've never actually heard a story of anybody being bitten by this. I'm not disputing that it was a useful change, but I think "extremely dangerous" is an exaggeration. > Py2 had several language features and misfeatures that are that > dangerous (having the simple name "input()" do evaluation is a trap > that MANY people have fallen into), and it's correct to fix that. If > Python had, from the start, treated tabs and spaces as different forms > of indentation, there would be no reason to change that now. There were also plenty of backward-incompatible changes in Py3 that had nothing to do with dangerous code. > Whether True and False are keywords or builtins is a matter of debate, > but there are definite advantages to them being locked down, and the > only real disadvantage that I see is the question of consistency (eg > "Ellipsis" is not a keyword, so you can still assign to that). The other disadvantages are: making the change was backward-incompatible, and it prevents the user from overriding their values, which might sometimes be useful in the same way that overriding print might sometimes be useful -- which was one of the reasons for demoting print from keyword status! > Having star imports be bypassed when looking for nonlocals is going to > be extremely confusing if you DO import a name from the other module. > There's no right answer to the nonlocal lookup question, so the best > thing to do is to not permit it. There's fundamentally no way for this > to be both legal and sane in all situations, so it can't be left up to > the linter. I disagree. Always using the variable that is explicitly assigned would be both legal and sane in all situations. It also allows an easy fix: just explicitly assign the variable in the scope where you actually want it. Yes, some people might be confused when their star import isn't picked up by nonlocal, but people also get confused by late binding of nonlocals, or the behavior of mutable default values, or the distinction between modifying a list and reassigning it, etc. etc. Nobody is suggesting that defining a closure inside a loop ought to be a SyntaxError, but it is probably something that linters should be looking for, if they don't already. > Mixing 'async def' and 'yield from' is, AIUI, more of a > NotImplementedError than a SyntaxError; the wording of the PEP > basically says that it's low priority, not that it's a bad thing. So > that one is never going to be flagged by a linter - once it's made > possible, it'll be the normal and expected behaviour, so there's no > reason to flag it (except perhaps as "beware that this is not backward > compatible with Python <3.8"). I was not referring to the possible future use of yield from for async generators; I was referring to the possibility *today* of using "yield from" as a synonym for *await*. As far as I know the only major obstacle to that is that the authors (with good reason) made it a SyntaxError. This is exactly the same sort of situation: it's a construct that would otherwise be perfectly valid, but it's made a SyntaxError specifically to prevent users from doing some the devs don't want them to. -- https://mail.python.org/mailman/listinfo/python-list
Re: Ideas about how software should behave (was: replacing `else` with `then` in `for` and `try`)
On Tue, Nov 7, 2017 at 4:28 PM, Steve D'Aprano wrote: > On Wed, 8 Nov 2017 04:28 am, Ian Kelly wrote: > >> Steve's manufactured interactive example ("manufactured" because >> who really uses for-else interactively? If I really care that much >> about output formatting I'm going to put it in a script). > > Me. As I have said. > > I really don't appreciate you implying that I'm lying about that. Sorry, I wasn't aware that you had said that. -- https://mail.python.org/mailman/listinfo/python-list
Re: Ideas about how software should behave (was: replacing `else` with `then` in `for` and `try`)
On Wed, 8 Nov 2017 04:28 am, Ian Kelly wrote: > Steve's manufactured interactive example ("manufactured" because > who really uses for-else interactively? If I really care that much > about output formatting I'm going to put it in a script). Me. As I have said. I really don't appreciate you implying that I'm lying about that. As for the question of whether anyone else uses it... that depends on whether there is anyone else: - using the REPL in an exploratory manner - entering loops with more than, say, two or three lines on the fly - that requires an additional block that has to run after the loop, without a pause for input - and they don't realise this until after they've started typing the loop (it's *exploratory* coding, which means sometimes you haven't thought things through until after you start typing) - AND they have the insight to realise that you can use an else block to rescue the situation without having to re-enter the lines already entered. Given how unfamiliar for...else is, it's probably only a small number of people that meet *all* these conditions, especially the last. I fear that most people wouldn't have the insight to realise that you can do this -- because they either don't know for...else at all, or they have the wrong mental model for it, or they simply aren't good at thinking outside the box. Who knows what other "thinking outside the box" uses for for...else with no break there are? Where there is one, there are probably others. The point is, if you require break and make the absence a syntax error, you rule them out. As things are today, the for block and the else block are loosely coupled. Apart from the requirement that else must immediately follow a for (or while) block, the language doesn't *force* there to be any coupling between the for block and the else block. We may consider them to be separate blocks, almost unrelated in principle (if not in practice). That has the conceptual advantage that we can teach, learn and think about the for and else blocks as separate concepts, which allows us to reason about them by composition: - we can reason about the for block as iteration over a sequence; - if we now add an else block after it, we don't have to revise our reasoning about the for block, we simply add the else block after it. Which is why I was able to think outside the box and realise I could rescue my already-typed dozen line for loop by adding an else clause. Whereas Jon's model requires us to change our understanding of the for block: - we reason about the for block as iteration; - if we then add an else block, we have to go back and re-interpret the for block as some sort of metaphorical search, whether or not it actually is a search, before we can think about the else block. Otherwise it doesn't make sense in his model of "search, else if not condition leading to break". In Jon's model, if we interpret else as "else no break", then we're also left with the mystery of what happened to the "if break" clause. -- Steve “Cheer up,” they said, “things could be worse.” So I cheered up, and sure enough, things got worse. -- https://mail.python.org/mailman/listinfo/python-list
Re: Ideas about how software should behave (was: replacing `else` with `then` in `for` and `try`)
On Wed, Nov 8, 2017 at 8:16 AM, Ian Kelly wrote: > All of these are things that a linter should probably catch and warn > about. If you had said that the break syntax suggestion was a good > idea but probably better suited as a linter warning than as a > SyntaxError integrated into the parser, then I would likely agree with > you. That's not what you said, though. You said the suggestion was > "ridiculous". Someone did mention linters at one point, and if I didn't explicitly agree, I certainly didn't disagree. Let me make my position clearer: The suggestion that these should be hard errors in the parser is ridiculous because it is not the parser's job to catch all bugs. Python is not intended to be that sort of language. It is the job of a linter to detect probable errors. >> Not one of these is syntactically invalid. Why should "else without >> break" be trapped by the parser? Your other examples mostly have good >> parser-level reasons for being errors > > No, they don't. All four of them could just as easily also be accepted > by the parser and only flagged as linter warnings. If everyone in the world agreed that a tab was equal to eight spaces, then I would agree that the tab/space discrepancy could be considered a linter warning. But there's no such agreement, which means that having the language declare some equivalency is extremely dangerous. Py2 had several language features and misfeatures that are that dangerous (having the simple name "input()" do evaluation is a trap that MANY people have fallen into), and it's correct to fix that. If Python had, from the start, treated tabs and spaces as different forms of indentation, there would be no reason to change that now. Whether True and False are keywords or builtins is a matter of debate, but there are definite advantages to them being locked down, and the only real disadvantage that I see is the question of consistency (eg "Ellipsis" is not a keyword, so you can still assign to that). Having star imports be bypassed when looking for nonlocals is going to be extremely confusing if you DO import a name from the other module. There's no right answer to the nonlocal lookup question, so the best thing to do is to not permit it. There's fundamentally no way for this to be both legal and sane in all situations, so it can't be left up to the linter. Mixing 'async def' and 'yield from' is, AIUI, more of a NotImplementedError than a SyntaxError; the wording of the PEP basically says that it's low priority, not that it's a bad thing. So that one is never going to be flagged by a linter - once it's made possible, it'll be the normal and expected behaviour, so there's no reason to flag it (except perhaps as "beware that this is not backward compatible with Python <3.8"). So, no, this is not the same. ChrisA -- https://mail.python.org/mailman/listinfo/python-list
Re: Ideas about how software should behave (was: replacing `else` with `then` in `for` and `try`)
On Tue, Nov 7, 2017 at 12:10 PM, Chris Angelico wrote: > On Wed, Nov 8, 2017 at 4:28 AM, Ian Kelly wrote: >> On Sat, Nov 4, 2017 at 6:40 AM, Chris Angelico wrote: >>> Maybe we're not defending the abuse of other contributors. Maybe we're >>> defending a legitimate, if somewhat caustic, response to a ridiculous >>> suggestion. >> >> I don't think it was a ridiculous suggestion. >> >> Assigment to False is a syntax error, even though it's lexically valid >> and was accepted in the past. > > Assignment to None was and is a syntax error, and assignment to False > was legal only for backward compatibility within the 2.x line. I'm not > sure what your point is. None, False, and True are all keywords, not > built-ins, so you can't assign to them (any more than you could assign > to a literal integer). That's a false equivalence. There is nothing about None, False or True that *requires* them to be keywords, and my point is that in Python 2, two out of the three were *not* keywords. Making them keywords was a backward-incompatible change and entirely unnecessary, but it was done because it was deemed to be worthwhile. >> Inconsistent indentation is a syntax error, even though it could be >> parsed and has been in the past. > > I'm not sure what you mean by "inconsistent" here, unless it's that > tabs and spaces had a declared equivalency that they now don't. Yes. > Unindenting to a level you've never used has always been an error; > being sloppy has never been: > > if 1: > if 2: > pass > pass # always an error > if 3: > pass # never an error > > Again, though, I'm not sure what your point is. Are you saying that it > was ridiculous (or called ridiculous) to separate tabs and spaces > rather than treat them as equivalent? Or are you saying that it ought > to be legal? No, my point is not about indentation. I listed these things as examples of useful syntax errors that are not unlike the for-else syntax error suggestion. In this case, the change to treat tabs and spaces separately for indentation was a good one, albeit backward incompatible, and the suggestion to disallow for-else without break is likewise a good one, albeit backward incompatible. >> Wildcard imports inside a function are a syntax error, even though >> it's lexically valid and mostly harmless. > > Mostly harmless? Hmm. Okay: > > def func1(): > spam = 1 > def func2(): > from module import * > def func3(): > nonlocal spam > spam += 1 > > What does func3's spam refer to? In my opinion, it should refer to the variable from func1, since the star import can't be assumed to introduce a "spam" variable, and it doesn't make sense for the meaning of the code (and the generated byte code content) to depend on whether it does. > I don't know for sure if that's why star imports got banned, but I > also don't know for sure what should happen in the above situation > either. I think it's more likely because fast locals don't support dynamic modification, the same reason why a call to exec() from a function body can't modify the local variables either. It's not that this is technically infeasible; it's just unsupported. >> Using "yield from" inside an async coroutine is a syntax error, even >> though it's lexically valid and "await" and "yield from" are nearly >> identical. > > I'm not sure about this one, but the equivalence of await and yield > from is a red herring. The part that's more surprising is this: > async def foo(): > ...yield from [1,2,3] > ... > File "", line 2 > SyntaxError: 'yield from' inside async function async def foo(): > ...for _ in [1,2,3]: yield _ > ... > > (Yes, I know "yield from" does a lot more than "for... yield" does) > > But in comparison to "for... break", this is definitely not an error > on the basis that it "makes no sense". It's more likely to be an error > because of some internal limitation, in the same way that async > coroutines weren't possible _at all_ initially: No, it isn't. They share implementation. The only difference between the two apart from the syntactic restrictions is that await validates the type of its argument and looks for a method called __await__ instead of __iter__; see PEP 492. I suspect that the reason for the restriction was to reserve lexical space for asynchronous generators to be supported in the future, although PEP 525 only permits yield and not yield from, having explicitly deferred yield from as "less critical" and "requiring serious redesign". >> I haven't seen any argument against making "else" without "break" a >> syntax error that wouldn't also apply to the above, with the exception >> of Steve's manufactured interactive example ("manufactured" because >> who really uses for-else interactively? If I really care that much >> about output formatting I'm going to put it in a script). If there is >> any extant code that would actually be broken by this, it's very >> likely buggy. > >
Re: Ideas about how software should behave (was: replacing `else` with `then` in `for` and `try`)
On Wed, Nov 8, 2017 at 4:28 AM, Ian Kelly wrote: > On Sat, Nov 4, 2017 at 6:40 AM, Chris Angelico wrote: >> On Sat, Nov 4, 2017 at 11:25 PM, Jon Ribbens >> wrote: >>> On 2017-11-04, Ben Finney wrote: To respond to the criticism of an idea – criticism containing no mention of the person – as though it “clearly refers to the [person]”, is of significant concern on a software dicussion forum such as this. >>> >>> No, the thing that is "of significant conern on a software discussion >>> forum such as this" is people such as yourself defending the abuse of >>> other contributors. >> >> Maybe we're not defending the abuse of other contributors. Maybe we're >> defending a legitimate, if somewhat caustic, response to a ridiculous >> suggestion. > > I don't think it was a ridiculous suggestion. > > Assigment to False is a syntax error, even though it's lexically valid > and was accepted in the past. Assignment to None was and is a syntax error, and assignment to False was legal only for backward compatibility within the 2.x line. I'm not sure what your point is. None, False, and True are all keywords, not built-ins, so you can't assign to them (any more than you could assign to a literal integer). > Inconsistent indentation is a syntax error, even though it could be > parsed and has been in the past. I'm not sure what you mean by "inconsistent" here, unless it's that tabs and spaces had a declared equivalency that they now don't. Unindenting to a level you've never used has always been an error; being sloppy has never been: if 1: if 2: pass pass # always an error if 3: pass # never an error Again, though, I'm not sure what your point is. Are you saying that it was ridiculous (or called ridiculous) to separate tabs and spaces rather than treat them as equivalent? Or are you saying that it ought to be legal? > Wildcard imports inside a function are a syntax error, even though > it's lexically valid and mostly harmless. Mostly harmless? Hmm. Okay: def func1(): spam = 1 def func2(): from module import * def func3(): nonlocal spam spam += 1 What does func3's spam refer to? I don't know for sure if that's why star imports got banned, but I also don't know for sure what should happen in the above situation either. > Using "yield from" inside an async coroutine is a syntax error, even > though it's lexically valid and "await" and "yield from" are nearly > identical. I'm not sure about this one, but the equivalence of await and yield from is a red herring. The part that's more surprising is this: >>> async def foo(): ...yield from [1,2,3] ... File "", line 2 SyntaxError: 'yield from' inside async function >>> async def foo(): ...for _ in [1,2,3]: yield _ ... (Yes, I know "yield from" does a lot more than "for... yield" does) But in comparison to "for... break", this is definitely not an error on the basis that it "makes no sense". It's more likely to be an error because of some internal limitation, in the same way that async coroutines weren't possible _at all_ initially: Python 3.5.3 (default, Jan 19 2017, 14:11:04) [GCC 6.3.0 20170118] on linux Type "help", "copyright", "credits" or "license" for more information. >>> async def foo(): yield 1 ... File "", line 1 SyntaxError: 'yield' inside async function That's no longer a SyntaxError as of 3.6, and I suspect that making "yield from" work inside an async function is, if not actually on the roadmap, certainly a possibility. > I haven't seen any argument against making "else" without "break" a > syntax error that wouldn't also apply to the above, with the exception > of Steve's manufactured interactive example ("manufactured" because > who really uses for-else interactively? If I really care that much > about output formatting I'm going to put it in a script). If there is > any extant code that would actually be broken by this, it's very > likely buggy. There are many MANY constructs that are broadly useless. Global declaration without assignment: >>> def foo(): ... global print ... print("hello") ... Unused variable (often indicates a misspelling): >>> def bar(): ... x = 1 ... return y ... Never-executed bodies: >>> def spam(): ... if False: print("ham") ... while False: print("ham") ... for _ in []: print("ham") ... try: pass ... except ZeroDivisionError: print("ham") ... (In CPython 3.7, the optimizer will eliminate the first two, but not the for or try. That could change, of course.) Not one of these is syntactically invalid. Why should "else without break" be trapped by the parser? Your other examples mostly have good parser-level reasons for being errors (you could argue from a language design POV about why False is a keyword but Ellipsis is just a built-in, but it's obvious that assigning to keywords has to be an error). Merely being pointless does not justify being an error; *maybe* the language co
Re: Ideas about how software should behave (was: replacing `else` with `then` in `for` and `try`)
On Sat, Nov 4, 2017 at 6:40 AM, Chris Angelico wrote: > On Sat, Nov 4, 2017 at 11:25 PM, Jon Ribbens > wrote: >> On 2017-11-04, Ben Finney wrote: >>> To respond to the criticism of an idea – criticism containing no mention >>> of the person – as though it “clearly refers to the [person]”, is of >>> significant concern on a software dicussion forum such as this. >> >> No, the thing that is "of significant conern on a software discussion >> forum such as this" is people such as yourself defending the abuse of >> other contributors. > > Maybe we're not defending the abuse of other contributors. Maybe we're > defending a legitimate, if somewhat caustic, response to a ridiculous > suggestion. I don't think it was a ridiculous suggestion. Assigment to False is a syntax error, even though it's lexically valid and was accepted in the past. Inconsistent indentation is a syntax error, even though it could be parsed and has been in the past. Wildcard imports inside a function are a syntax error, even though it's lexically valid and mostly harmless. Using "yield from" inside an async coroutine is a syntax error, even though it's lexically valid and "await" and "yield from" are nearly identical. I haven't seen any argument against making "else" without "break" a syntax error that wouldn't also apply to the above, with the exception of Steve's manufactured interactive example ("manufactured" because who really uses for-else interactively? If I really care that much about output formatting I'm going to put it in a script). If there is any extant code that would actually be broken by this, it's very likely buggy. -- https://mail.python.org/mailman/listinfo/python-list
Re: Ideas about how software should behave (was: replacing `else` with `then` in `for` and `try`)
On Fri, Nov 3, 2017 at 11:55 PM, Ben Finney wrote: > Ian Kelly writes: > >> Please stop defending the use of incivility on this list. > > Please stop conflating people, who deserve civility, with ideas. We must > not allow the civility deserved by people, to prevent us from > criticising any ideas — especially not ideas about the behaviour of > software. No, I won't. I once believed this, too. I used it as a defense for criticism of religious ideas. "Oh, I'm not attacking the believers in religion. I'm attacking the *ideas* of religion." And I meant it, too: I wasn't *trying* to insult anybody when I would say that religious belief was foolish and ignorant. Nowadays I realize and accept that this is preposterous. You cannot criticize an idea without also criticizing the people who are attached to that idea. Even if no personal slight is intended, it is received that way. If your idea is bad, then by implication you are a person with bad ideas. Now, I'm not saying that we can't criticize ideas. We can, however, choose to be polite or not in how we go about it. -- https://mail.python.org/mailman/listinfo/python-list
Re: Ideas about how software should behave (was: replacing `else` with `then` in `for` and `try`)
On Sat, Nov 4, 2017 at 11:25 PM, Jon Ribbens wrote: > On 2017-11-04, Ben Finney wrote: >> To respond to the criticism of an idea – criticism containing no mention >> of the person – as though it “clearly refers to the [person]”, is of >> significant concern on a software dicussion forum such as this. > > No, the thing that is "of significant conern on a software discussion > forum such as this" is people such as yourself defending the abuse of > other contributors. Maybe we're not defending the abuse of other contributors. Maybe we're defending a legitimate, if somewhat caustic, response to a ridiculous suggestion. ChrisA -- https://mail.python.org/mailman/listinfo/python-list
Re: Ideas about how software should behave (was: replacing `else` with `then` in `for` and `try`)
On 2017-11-04, Ben Finney wrote: > To respond to the criticism of an idea – criticism containing no mention > of the person – as though it “clearly refers to the [person]”, is of > significant concern on a software dicussion forum such as this. No, the thing that is "of significant conern on a software discussion forum such as this" is people such as yourself defending the abuse of other contributors. -- https://mail.python.org/mailman/listinfo/python-list