Re: Ideas about how software should behave (was: replacing `else` with `then` in `for` and `try`)

2017-11-08 Thread Ian Kelly
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`)

2017-11-08 Thread Chris Angelico
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`)

2017-11-08 Thread Ian Kelly
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`)

2017-11-08 Thread Chris Angelico
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`)

2017-11-08 Thread Ian Kelly
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`)

2017-11-08 Thread Chris Angelico
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`)

2017-11-08 Thread Ian Kelly
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`)

2017-11-07 Thread Ian Kelly
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`)

2017-11-07 Thread Steve D'Aprano
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`)

2017-11-07 Thread Chris Angelico
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`)

2017-11-07 Thread Ian Kelly
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`)

2017-11-07 Thread Chris Angelico
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`)

2017-11-07 Thread Ian Kelly
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`)

2017-11-07 Thread Ian Kelly
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`)

2017-11-04 Thread Chris Angelico
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`)

2017-11-04 Thread Jon Ribbens
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