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: replacing `else` with `then` in `for` and `try`

2017-11-06 Thread Random832
I haven't read over every message in the thread, so sorry if this has
been suggested before, but how about "if not break:" and "if not
except:" as synonyms for the current 'else' clause? They're already
keywords, and this sequence of keywords has no current meaning.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: replacing 'else' with 'then' in 'for' and 'try'

2017-11-06 Thread ROGER GRAYDON CHRISTMAN
Just a little two-cent opinion from the peanut gallery:


I've been following all the discussion on this go by, sometimes getting

a bit heated at times, and just sitting nice and safe and secure in my

little ivory tower, where I simply tell my students to not use 'break'.


As a stodgy educator, I usually restrict them for these two reasons:

1) the loop condition should describe your expected loop conditions, and

2) the exception handling structure allows more control over where

 the exceptional circumstances will be handled (including which function)


When it comes to searching an iterable collection, my ivory-tower

view point tells me that the looping condition is based on whether the

item is found, and is not a for loop traversing the entirety.

To me, that is the 'one obvious way to do it'


If I expect the item will be found, but fear that it will not, I can always
compare

a subscript to len(), or if that seems too hard, catch the StopIteration
exception.

I only recommend the for loop when the true expectation is to visit

the entire collection (which can later be moderated with iter's sentinel

parameter, or some of the filters in itertools)


And I see that simply removing 'break' from my vocabulary, this

whole 'else on a loop' issue completely dissolves.


So thank you for, even unintentionally, helping me to feel good

about living inside my ivory tower!


Roger Christman

Pennsylvania State University
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: replacing `else` with `then` in `for` and `try`

2017-11-06 Thread Ned Batchelder

On 11/6/17 8:05 AM, Jon Ribbens wrote:

On 2017-11-06, Chris Angelico  wrote:

If you start with the assumption that "intuitively obvious" doesn't
actually mean "intuitively obvious" but actually means something
completely different, then your statement definitely means something
non-contradictory. But if you start with the assumption that
"intuitively obvious" really does mean that the purpose and meaning of
for-else can be understood easily without external information, then
your statement contradicts itself.

I didn't say that 'for...else' was inherently "intutively obvious".
In fact I said the opposite of that. I said that *if* you start from
the right premise then it *becomes* intuitively obvious.


This is comp.lang.python, not alt.english.remedial, so we expect you
to use English competently, or at least accept correction when you
misuse words.

I'm glad your expectations are being met then. You might want to work
on also reading English competently, and then everyone will be happy!


As I said, I've provided a solution to the problem, what more
do you want? This feels very much like you're arguing for
argument's sake, which is a game I'm not willing to play along
with for much longer.

Except that you haven't. Your proposed solution is incorrect and false.

Yes, your logical argument there as to why is undeniable. I must admit
that your little gang's assertion that I'm foolish and mistaken because
I find Python's syntax simple to understand and you find it hard to
understand seems a little contradictory.


Ugh, can't we all just give each other the benefit of the doubt, and use 
the principle of charity?  It's easy to miscommunicate in a purely 
textual medium.   Everyone just take your foot off the "i'm right and 
you're wrong" gas pedal for moment.


--Ned.
--
https://mail.python.org/mailman/listinfo/python-list


Re: replacing `else` with `then` in `for` and `try`

2017-11-06 Thread Chris Angelico
On Tue, Nov 7, 2017 at 12:05 AM, Jon Ribbens  wrote:
> On 2017-11-06, Chris Angelico  wrote:
>> If you start with the assumption that "intuitively obvious" doesn't
>> actually mean "intuitively obvious" but actually means something
>> completely different, then your statement definitely means something
>> non-contradictory. But if you start with the assumption that
>> "intuitively obvious" really does mean that the purpose and meaning of
>> for-else can be understood easily without external information, then
>> your statement contradicts itself.
>
> I didn't say that 'for...else' was inherently "intutively obvious".
> In fact I said the opposite of that. I said that *if* you start from
> the right premise then it *becomes* intuitively obvious.

If you have to start by explaining a premise, it's not intuitive.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: replacing `else` with `then` in `for` and `try`

2017-11-06 Thread Jon Ribbens
On 2017-11-06, Chris Angelico  wrote:
> If you start with the assumption that "intuitively obvious" doesn't
> actually mean "intuitively obvious" but actually means something
> completely different, then your statement definitely means something
> non-contradictory. But if you start with the assumption that
> "intuitively obvious" really does mean that the purpose and meaning of
> for-else can be understood easily without external information, then
> your statement contradicts itself.

I didn't say that 'for...else' was inherently "intutively obvious".
In fact I said the opposite of that. I said that *if* you start from
the right premise then it *becomes* intuitively obvious.

> This is comp.lang.python, not alt.english.remedial, so we expect you
> to use English competently, or at least accept correction when you
> misuse words.

I'm glad your expectations are being met then. You might want to work
on also reading English competently, and then everyone will be happy!

>> As I said, I've provided a solution to the problem, what more
>> do you want? This feels very much like you're arguing for
>> argument's sake, which is a game I'm not willing to play along
>> with for much longer.
>
> Except that you haven't. Your proposed solution is incorrect and false.

Yes, your logical argument there as to why is undeniable. I must admit
that your little gang's assertion that I'm foolish and mistaken because
I find Python's syntax simple to understand and you find it hard to
understand seems a little contradictory.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: replacing `else` with `then` in `for` and `try`

2017-11-06 Thread Chris Angelico
On Mon, Nov 6, 2017 at 10:34 PM, Jon Ribbens  wrote:
> On 2017-11-06, Ben Finney  wrote:
>> Jon Ribbens  writes:
>>> On 2017-11-05, Ben Finney  wrote:
>>> > Jon Ribbens  writes:
>>> >> I've provided you with a way of thinking about 'for...else' that makes
>>> >> its purpose and meaning intuitively obvious.
>>> >
>>> > I've read that sentence several times, and I still can't make it
>>> > anything but a contradiction in terms.
>>>
>>> Well, keep at it and I'm sure you'll work it out eventually.
>>
>> You don't want to provide me with a way of thinking about it that makes
>> it mean something non-contradictory? :-)
>
> It already does mean something non-contradictory. This is
> comp.lang.python (or python-list), not alt.english.remedial.
> If you start from the wrong premise, as Steve is doing, then
> even the most obvious of things can be rendered opaque and
> confusing.

If you start with the assumption that "intuitively obvious" doesn't
actually mean "intuitively obvious" but actually means something
completely different, then your statement definitely means something
non-contradictory. But if you start with the assumption that
"intuitively obvious" really does mean that the purpose and meaning of
for-else can be understood easily without external information, then
your statement contradicts itself.

This is comp.lang.python, not alt.english.remedial, so we expect you
to use English competently, or at least accept correction when you
misuse words.

> As I said, I've provided a solution to the problem, what more
> do you want? This feels very much like you're arguing for
> argument's sake, which is a game I'm not willing to play along
> with for much longer.

Except that you haven't. Your proposed solution is incorrect and false.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: replacing `else` with `then` in `for` and `try`

2017-11-06 Thread bartc

On 06/11/2017 02:28, Steve D'Aprano wrote:

On Sat, 4 Nov 2017 03:57 pm, Michael Torrie wrote:



Can you be more specific? What are some of these "many" ways of aborting
a loop?  Help a guy out here.


Aside from more exotic methods such as os.abort, os._exit and signal handlers,
the common ways of breaking out of a loop are:

- raise
- return
- break

Am I being pedantic? Of course I am. But we're programmers -- if we don't have
an accurate and complete understanding of code, who will? Given how many
people find it difficult to understand the semanics of for...else, I think we
need to be pedantic about it.


Take this for-loop:

for I in R:
A
else:
B
C

Here are the various ways of exiting the loop, with Y or N indicating 
whether that particular block (or 'suite') is executed:


  B   C

  Normal termination: Y   Y
  Break from A:   N   Y
  Raise/return/etc from A:N   N

Here, we're only interested in whether B and C have different entries, 
as that would be the only reason to have an 'else' part in the first place.


And that only happens when the loop is terminated with a Break. Unless 
someone knows of any other circumstances where B is not executed but C 
is. (Both B and C also contain raise, return, exit(), infinite loops 
etc, but that shouldn't effect this point.)


Break inside the loop can also be conditional (I think it has to be if 
you want more than one iteration!), which means that sometimes, it will 
never break, then you get the Y/Y (or N/N) result. But the expectation 
is that there the break COULD be executed, so you will need the 'else'.


--
bartc
--
https://mail.python.org/mailman/listinfo/python-list


Re: replacing `else` with `then` in `for` and `try`

2017-11-06 Thread Jon Ribbens
On 2017-11-06, Ben Finney  wrote:
> Jon Ribbens  writes:
>> On 2017-11-05, Ben Finney  wrote:
>> > Jon Ribbens  writes:
>> >> I've provided you with a way of thinking about 'for...else' that makes
>> >> its purpose and meaning intuitively obvious.
>> >
>> > I've read that sentence several times, and I still can't make it
>> > anything but a contradiction in terms.
>>
>> Well, keep at it and I'm sure you'll work it out eventually.
>
> You don't want to provide me with a way of thinking about it that makes
> it mean something non-contradictory? :-)

It already does mean something non-contradictory. This is
comp.lang.python (or python-list), not alt.english.remedial.
If you start from the wrong premise, as Steve is doing, then
even the most obvious of things can be rendered opaque and
confusing.

As I said, I've provided a solution to the problem, what more
do you want? This feels very much like you're arguing for
argument's sake, which is a game I'm not willing to play along
with for much longer.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: replacing `else` with `then` in `for` and `try`

2017-11-05 Thread Steve D'Aprano
On Sat, 4 Nov 2017 03:57 pm, Michael Torrie wrote:

> On 11/03/2017 09:06 PM, Chris Angelico wrote:
>> On Sat, Nov 4, 2017 at 1:57 PM, Michael Torrie  wrote:
>>> On 11/03/2017 07:09 PM, Steve D'Aprano wrote:
 On Sat, 4 Nov 2017 06:15 am, Michael Torrie wrote:

> In fact if you have no break you may as well drop the
> else entirely, because the block will always execute.

 That's incorrect. There are multiple ways to exit a loop that will
 prevent the `else` block from executing, `break` is only one.
>>>
>>> Such as?
>> 
>> There are many. But other than break, I don't know of any that WOULD
>> execute the next line of code immediately _after_ the loop.
> 
> Can you be more specific? What are some of these "many" ways of aborting
> a loop?  Help a guy out here.

Aside from more exotic methods such as os.abort, os._exit and signal handlers,
the common ways of breaking out of a loop are:

- raise
- return
- break

Am I being pedantic? Of course I am. But we're programmers -- if we don't have
an accurate and complete understanding of code, who will? Given how many
people find it difficult to understand the semanics of for...else, I think we
need to be pedantic about it.

I raise these because such commonplace ways of exiting a loop rules out
suggestions that we think of or rename `else` as "else no break"
or "finally":

(1) `else no break` is misleading as it implies that `break` is the only way
to avoid running the block;

(2) `finally` is misleading as it suggests that the block runs even when you
raise or return out of the loop, like a try...finally block.


> I know, for example, that we have exceptions. But those hardly matter in
> this discussion because they wouldn't execute the else clause either.

That contradicts what you said earlier:

"if you have no break the [else] block will always execute."

Of course you are right -- an exception will also prevent the `else` clause
from running. But that's not what you said earlier. Hence my correction.

The fact that `raise` and `return` avoid running the `else` block is not a
given. We cannot afford to say "that's so obvious it doesn't need to be
said". It isn't obvious. There are at least two other code blocks that make
guarantees about code "always"[1] running, even if you raise or return:

- in a try...except...else block, the `finally` block will still run;

- in a `with` block, the context manager's `__exit__` method will usually run
(it depends on the context manager).



[1] For reasonable values of "always". Obviously if you drop a 1000 tonne
weight on the computer, the `finally` clause will not get a chance to run
before the CPU is crushed into powder :-)


-- 
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: replacing `else` with `then` in `for` and `try`

2017-11-05 Thread Steve D'Aprano
On Mon, 6 Nov 2017 01:39 am, Jon Ribbens wrote:

> On 2017-11-05, Steve D'Aprano  wrote:
>> On Sat, 4 Nov 2017 04:44 am, Jon Ribbens wrote:
>>> That conforms to my model. It's searching for the condition
>>> 'count > MAX_OBJECTS'.
>>
>> That's sounds to me that you are willing to call just about any test of a
>> condition inside a loop a "search". I don't think that's helpful. I think
>> it is mangling the word to the point it is meaningless.
> 
> You're entitled to your opinion, of course. I've provided you with a
> way of thinking about 'for...else' that makes its purpose and meaning
> intuitively obvious.

By definition, if people have to learn the "right mental model" (as opposed to
the one which just comes to them naturally) then there is nothing intuitive
about it.


[...]
>> I find the code useful. I shouldn't have to justify why it is useful to me,
>> but for the record it especially comes in handy when I've already typed out
>> a multi-line loop in the REPL, and only then realised that I'll need some
>> way to add an extra line at the end.
> 
> Just press up arrow to go back and edit the first line of your
> current input and insert an 'if 1:' as someone else suggested.

"Just press up arrow" -- and that will magically fill in the other 10 lines I
typed, will it?

Don't be so condescending. I know how to use up-arrow, and I even described
using it, which you cut out of your reply.

That's a pretty dishonest trick. You saw that I had already discussed the
limitations of using up-arrow to retrieve lines from command line history,
but rather than acknowledge that, you deleted my comment and added
condescending and useless "advice" to make me seem like I don't even know
something as simple as up-arrow.



-- 
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: replacing `else` with `then` in `for` and `try`

2017-11-05 Thread Chris Angelico
On Mon, Nov 6, 2017 at 11:06 AM, Steve D'Aprano
 wrote:
> On Mon, 6 Nov 2017 10:06 am, Jon Ribbens wrote:
>
>> On 2017-11-05, Ben Finney  wrote:
>>> Jon Ribbens  writes:
 I've provided you with a way of thinking about 'for...else' that makes
 its purpose and meaning intuitively obvious.
>>>
>>> I've read that sentence several times, and I still can't make it
>>> anything but a contradiction in terms.
>>
>> Well, keep at it and I'm sure you'll work it out eventually.
>
>
> Alice laughed. 'There's no use trying,' she said. 'One can't
> believe impossible things.'
>
> 'I daresay you haven't had much practice,' said the Queen.
> 'When I was your age, I always did it for half-an-hour a day.
> Why, sometimes I've believed as many as six impossible things
> before breakfast.'

Yes, that. Although I was more thinking of the word "intuitively":

  `When _I_ use a word,' Humpty Dumpty said in rather a scornful
tone, `it means just what I choose it to mean -- neither more nor
less.'

  `The question is,' said Alice, `whether you CAN make words mean
so many different things.'

  `The question is,' said Humpty Dumpty, `which is to be master -
- that's all.'

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: replacing `else` with `then` in `for` and `try`

2017-11-05 Thread Steve D'Aprano
On Mon, 6 Nov 2017 10:06 am, Jon Ribbens wrote:

> On 2017-11-05, Ben Finney  wrote:
>> Jon Ribbens  writes:
>>> I've provided you with a way of thinking about 'for...else' that makes
>>> its purpose and meaning intuitively obvious.
>>
>> I've read that sentence several times, and I still can't make it
>> anything but a contradiction in terms.
> 
> Well, keep at it and I'm sure you'll work it out eventually.


Alice laughed. 'There's no use trying,' she said. 'One can't 
believe impossible things.'

'I daresay you haven't had much practice,' said the Queen. 
'When I was your age, I always did it for half-an-hour a day.
Why, sometimes I've believed as many as six impossible things
before breakfast.'



-- 
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: replacing `else` with `then` in `for` and `try`

2017-11-05 Thread Ben Finney
Jon Ribbens  writes:

> On 2017-11-05, Ben Finney  wrote:
> > Jon Ribbens  writes:
> >> I've provided you with a way of thinking about 'for...else' that makes
> >> its purpose and meaning intuitively obvious.
> >
> > I've read that sentence several times, and I still can't make it
> > anything but a contradiction in terms.
>
> Well, keep at it and I'm sure you'll work it out eventually.

You don't want to provide me with a way of thinking about it that makes
it mean something non-contradictory? :-)

-- 
 \ “Capitalism has destroyed our belief in any effective power but |
  `\  that of self interest backed by force.” —George Bernard Shaw |
_o__)  |
Ben Finney

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: replacing `else` with `then` in `for` and `try`

2017-11-05 Thread Jon Ribbens
On 2017-11-05, Ben Finney  wrote:
> Jon Ribbens  writes:
>> I've provided you with a way of thinking about 'for...else' that makes
>> its purpose and meaning intuitively obvious.
>
> I've read that sentence several times, and I still can't make it
> anything but a contradiction in terms.

Well, keep at it and I'm sure you'll work it out eventually.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: replacing `else` with `then` in `for` and `try`

2017-11-05 Thread Ben Finney
Jon Ribbens  writes:

> I've provided you with a way of thinking about 'for...else' that makes
> its purpose and meaning intuitively obvious.

I've read that sentence several times, and I still can't make it
anything but a contradiction in terms.

Something that is “intuitively obvious” surely has the property that it
*does not need* a special “way of thinking about” it.

So I can't see that it could be “intuitively obvious” if that special
way of thinking about it is needed. Did you mean something else?

-- 
 \   “Don't worry about what anybody else is going to do. The best |
  `\ way to predict the future is to invent it.” —Alan Kay |
_o__)  |
Ben Finney

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: replacing `else` with `then` in `for` and `try`

2017-11-05 Thread Jon Ribbens
On 2017-11-05, Steve D'Aprano  wrote:
> On Sat, 4 Nov 2017 04:44 am, Jon Ribbens wrote:
>> That conforms to my model. It's searching for the condition
>> 'count > MAX_OBJECTS'.
>
> That's sounds to me that you are willing to call just about any test of a
> condition inside a loop a "search". I don't think that's helpful. I think it
> is mangling the word to the point it is meaningless.

You're entitled to your opinion, of course. I've provided you with a
way of thinking about 'for...else' that makes its purpose and meaning
intuitively obvious. You'd apparently prefer to think about it a
different way that makes it counter-intuitive, and would like to
change the language to match your thinking instead. I'd regretfully
suggest that that is not going to happen.

> How about a loop that exits at some random time? Is that a search?
>
> for i in range(100, 0, -1):
> if flip_coin() == 'Heads':

Of course, that's searching for the condition "flip_coin() == 'Heads'".

> What you actually wrote, in various posts:
>
> You have a 'for...else' with no 'break'. Like I said, that should
> probably be a syntax error.
>
> if what the 'for' clause is doing doesn't match the concept 
> of 'searching for a match' then it's obvious that you shouldn't
> be using 'for...else' in the first place.
>
> the language doesn't currently strictly enforce the requirement
> for a 'break', but nevertheless if you don't have one you almost
> certainly have a bug.
>
> I stand by my comment as an accurate description of your response.

You're conflating two completely different points:

  * whether to allow 'for...else' with no 'break'
  * how to think about 'for...else' with a 'break'

My comment about syntax errors only has any relevance at all to the
former point.

> I find the code useful. I shouldn't have to justify why it is useful to me,
> but for the record it especially comes in handy when I've already typed out a
> multi-line loop in the REPL, and only then realised that I'll need some way
> to add an extra line at the end.

Just press up arrow to go back and edit the first line of your
current input and insert an 'if 1:' as someone else suggested.

> And yes, a better REPL would also solve that problem. But I have to use the
> REPL that exists, not the imaginary one that I'd like. If you want to call
> this a hackish work around for a limitation of the REPL, I'll say... okay.
> What's your point? It is still useful.

The question isn't whether it's useful, but whether it's *more* useful
than preventing bugs in peoples' code. You're entitled to your opinion
on that, and I'm entitled to mine, and neither opinion is 'arrogant'.

We're all just making guesses in the dark, unless anybody has any
statistics about how much time is wasted each year by bugs caused by
'for...else' with no 'break' and how much time would be wasted each
year by people being unable to use your REPL trick.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: replacing `else` with `then` in `for` and `try`

2017-11-04 Thread Steve D'Aprano
On Sat, 4 Nov 2017 04:44 am, Jon Ribbens wrote:

> On 2017-11-03, Steve D'Aprano  wrote:
>> The for loop does not necessarily perform a search:
>>
>> count = 1
>> for obj in sequence:
>> if count > MAX_OBJECTS:
>> print("too many objects, halting")
>> break
>> process(obj)
>> else:
>> print("finished")
>>
>> According to your mental model, this code is... what? Illegal? Silly?
>> Impossible? A syntax error?
> 
> That conforms to my model. It's searching for the condition
> 'count > MAX_OBJECTS'.

That's sounds to me that you are willing to call just about any test of a
condition inside a loop a "search". I don't think that's helpful. I think it
is mangling the word to the point it is meaningless.

How about a loop that exits at some random time? Is that a search?


for i in range(100, 0, -1):
if flip_coin() == 'Heads':
print("surprise!")
break
print("still running")
else:
print("countdown completed")


[...]
>> Your response to code that doesn't match your mental model is to say
>> that it is obviously wrong and probably buggy and should be made
>> into a syntax error if possible.
> 
> No, it isn't. Try reading again what I actually wrote.

What you actually wrote, in various posts:

You have a 'for...else' with no 'break'. Like I said, that should
probably be a syntax error.

if what the 'for' clause is doing doesn't match the concept 
of 'searching for a match' then it's obvious that you shouldn't
be using 'for...else' in the first place.

the language doesn't currently strictly enforce the requirement
for a 'break', but nevertheless if you don't have one you almost
certainly have a bug.


I stand by my comment as an accurate description of your response.


>> Ah yes, because it is inconceivable that anyone might have thought of a use
>> for for...else without a break.
> 
> It's not inconceivable, but nobody has thought of a sensible use so far
> (by which I mean one that shows it's a useful feature).

I find the code useful. I shouldn't have to justify why it is useful to me,
but for the record it especially comes in handy when I've already typed out a
multi-line loop in the REPL, and only then realised that I'll need some way
to add an extra line at the end. Since I spend a lot of time in the REPL
doing exploratory coding, this happens more often than I'd like.

Of course I could cancel the edit, then add in some sort of scaffolding code
to allow me to print an extra line at the end, then hit the up arrow
repeatedly to re-enter the lines I've already typed, editing them to fit the
scaffolding, then add the final print.

But that's tedious and painful and a waste of time and effort when it is
trivially easy to just add "else: print()". That is *simple* and it *works*
and it solves the problem.

And yes, a better REPL would also solve that problem. But I have to use the
REPL that exists, not the imaginary one that I'd like. If you want to call
this a hackish work around for a limitation of the REPL, I'll say... okay.
What's your point? It is still useful.

Try thinking outside the box. There's nothing wrong with finding unusual and
hackish uses for flow control statements.


[...]
>>> It's an incredibly obscure work-around for a different problem,
>>
>> You mean a different problem to "searching"? Yes indeed it is.
> 
> No, I mean a problem that has nothing to do with 'for...else' clauses.

I would say that it has nothing to do with the original motivation for
introducing for...else clauses into the language. Since it uses for...else,
it is pretty obtuse to deny that it has anything to do with for...else.

The for...else control statement is a tool. We can use tools for any purpose
we want, not just the ones that they were originally designed for. You are
declaring that a perfectly useful, albeit hackish, trick for the REPL is
illegitimate because it doesn't match your mental model.


-- 
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: replacing `else` with `then` in `for` and `try`

2017-11-04 Thread Chris Angelico
On Sat, Nov 4, 2017 at 11:22 PM, Jon Ribbens  wrote:
> On 2017-11-04, Michael Torrie  wrote:
>> On 11/03/2017 09:06 PM, Chris Angelico wrote:
>>> On Sat, Nov 4, 2017 at 1:57 PM, Michael Torrie  wrote:
 On 11/03/2017 07:09 PM, Steve D'Aprano wrote:
> That's incorrect. There are multiple ways to exit a loop that
> will prevent the `else` block from executing, `break` is only one.

 Such as?
>>>
>>> There are many. But other than break, I don't know of any that WOULD
>>> execute the next line of code immediately _after_ the loop.
>>
>> Can you be more specific? What are some of these "many" ways of aborting
>> a loop?  Help a guy out here.
>>
>> I know, for example, that we have exceptions. But those hardly matter in
>> this discussion because they wouldn't execute the else clause either.
>> They'd either be caught elsewhere, or end the program.  sys.exit() can
>> also terminate a for loop, but it terminates the whole program without
>> running the else statement.
>
> Yes, those are the sort of thing that Steve was referring to.
> He was being unhelpfully pedantic. A giant meteor destroying
> the computer the program was running on would prevent the 'else'
> block from executing too.

My definition of "preventing else from executing" is that it would (a)
not execute code inside the else block, and (b) execute unindented
code immediately *after* that else block. Consider a try/finally
block:

try:
print("Setup")
...
finally:
print("Cleanup")
print("Carrying on")

Before we reach "carrying on", we are guaranteed to pass through
"cleanup". Steve's pedantry is 100% accurate for situations where the
setup and cleanup involve the network; you can't actually guarantee
that the cleanup will be performed (a hard exit will abort the whole
process, a 'kill -9' will shut you down, powering down the computer
means nothing happens), so you have to assume that the cleanup might
not happen (eg with PostgreSQL, the database server will roll back
your transaction and clean up the trash). But AFAIK there is no way to
reach "carrying on" without first executing "cleanup".

With the for-else clause, we have the same valid pedantry, but with a
few differences. A 'return' inside the loop will skip the 'else'
clause (but wouldn't skip a 'finally'), as will any exception. But
neither of those would hit "carrying on" either. AFAIK the only way to
skip the else *and hit the "carrying on" call* is to use 'break'.
That's a non-pedantic interpretation of "skip the else clause".

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 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


Re: replacing `else` with `then` in `for` and `try`

2017-11-04 Thread Jon Ribbens
On 2017-11-04, Michael Torrie  wrote:
> On 11/03/2017 09:06 PM, Chris Angelico wrote:
>> On Sat, Nov 4, 2017 at 1:57 PM, Michael Torrie  wrote:
>>> On 11/03/2017 07:09 PM, Steve D'Aprano wrote:
 That's incorrect. There are multiple ways to exit a loop that
 will prevent the `else` block from executing, `break` is only one.
>>>
>>> Such as?
>> 
>> There are many. But other than break, I don't know of any that WOULD
>> execute the next line of code immediately _after_ the loop.
>
> Can you be more specific? What are some of these "many" ways of aborting
> a loop?  Help a guy out here.
>
> I know, for example, that we have exceptions. But those hardly matter in
> this discussion because they wouldn't execute the else clause either.
> They'd either be caught elsewhere, or end the program.  sys.exit() can
> also terminate a for loop, but it terminates the whole program without
> running the else statement.

Yes, those are the sort of thing that Steve was referring to.
He was being unhelpfully pedantic. A giant meteor destroying
the computer the program was running on would prevent the 'else'
block from executing too.
-- 
https://mail.python.org/mailman/listinfo/python-list


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

2017-11-03 Thread Ben Finney
Ian Kelly  writes:

> Steve was clearly referring to the coder, not the code.

Not at all. Steve was referring specifically to the *idea*:

[A ‘for … else’ structure without a ‘break’] should absolutely not
be a syntax error. There's no reason for it to be a syntax error,
except to satisfy some arrogant and foolish idea of purity.

This is clearly a criticism of the idea behind the expectation of a
syntax error. It doesn't refer to the coder, it refers explicitly to the
idea being criticised.

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.

> 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.

-- 
 \  “I used to be a proofreader for a skywriting company.” —Steven |
  `\Wright |
_o__)  |
Ben Finney

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: replacing `else` with `then` in `for` and `try`

2017-11-03 Thread Michael Torrie
On 11/03/2017 09:06 PM, Chris Angelico wrote:
> On Sat, Nov 4, 2017 at 1:57 PM, Michael Torrie  wrote:
>> On 11/03/2017 07:09 PM, Steve D'Aprano wrote:
>>> On Sat, 4 Nov 2017 06:15 am, Michael Torrie wrote:
>>>
 In fact if you have no break you may as well drop the
 else entirely, because the block will always execute.
>>>
>>> That's incorrect. There are multiple ways to exit a loop that will prevent 
>>> the
>>> `else` block from executing, `break` is only one.
>>
>> Such as?
> 
> There are many. But other than break, I don't know of any that WOULD
> execute the next line of code immediately _after_ the loop.

Can you be more specific? What are some of these "many" ways of aborting
a loop?  Help a guy out here.

I know, for example, that we have exceptions. But those hardly matter in
this discussion because they wouldn't execute the else clause either.
They'd either be caught elsewhere, or end the program.  sys.exit() can
also terminate a for loop, but it terminates the whole program without
running the else statement.




-- 
https://mail.python.org/mailman/listinfo/python-list


Re: replacing `else` with `then` in `for` and `try`

2017-11-03 Thread Chris Angelico
On Sat, Nov 4, 2017 at 1:57 PM, Michael Torrie  wrote:
> On 11/03/2017 07:09 PM, Steve D'Aprano wrote:
>> On Sat, 4 Nov 2017 06:15 am, Michael Torrie wrote:
>>
>>> In fact if you have no break you may as well drop the
>>> else entirely, because the block will always execute.
>>
>> That's incorrect. There are multiple ways to exit a loop that will prevent 
>> the
>> `else` block from executing, `break` is only one.
>
> Such as?

There are many. But other than break, I don't know of any that WOULD
execute the next line of code immediately _after_ the loop.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: replacing `else` with `then` in `for` and `try`

2017-11-03 Thread Michael Torrie
On 11/03/2017 07:09 PM, Steve D'Aprano wrote:
> On Sat, 4 Nov 2017 06:15 am, Michael Torrie wrote:
> 
>> In fact if you have no break you may as well drop the
>> else entirely, because the block will always execute.
> 
> That's incorrect. There are multiple ways to exit a loop that will prevent the
> `else` block from executing, `break` is only one.

Such as?
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: replacing `else` with `then` in `for` and `try`

2017-11-03 Thread Steve D'Aprano
On Sat, 4 Nov 2017 06:15 am, Michael Torrie wrote:

> In fact if you have no break you may as well drop the
> else entirely, because the block will always execute.

That's incorrect. There are multiple ways to exit a loop that will prevent the
`else` block from executing, `break` is only one.



-- 
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: replacing `else` with `then` in `for` and `try`

2017-11-03 Thread Ian Kelly
On Fri, Nov 3, 2017 at 3:25 PM, Stefan Ram  wrote:
> Jon Ribbens  writes:
>>No, it's an obvious bug. You have a 'for...else' with no 'break'.
>>Like I said, that should probably be a syntax error.
>
>   It should make the syntax of Python much more complicated,
>   when one would try to encode this rule in the /syntax/.
>
>   (Just try to write down the EBNF.)
>
>   It would be more reasonable to call it a constraint.
>   Maybe it could still be a parser error (not a runtime
>   error).

Regardless of whether it's encoded in the EBNF or a constraint on the
resulting parse tree, the eventual outcome would still be called a
syntax error.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: replacing `else` with `then` in `for` and `try`

2017-11-03 Thread Michael Torrie
On 11/03/2017 11:44 AM, Jon Ribbens wrote:
> And that's leading you into confusion, as you've demonstrated.

And indeed I've been led into considerable confusion about the else:
clause over the years. Every time I need to use it, I run a python shell
and try it out to remind myself how it works.  However now with your
mental model, Jon, I think I finally have it! Thank you.

I can't think of any normal circumstance where for/else is useful
without a break.  In fact if you have no break you may as well drop the
else entirely, because the block will always execute.  A linter should
definitely flag this.  One reason to leave it as valid syntax is maybe I
am coding up some skeleton code that I plan to fill in later.  So for
now the loop falls through, but at some future point I'll have finished
the searching code and added the break.  But if it were a syntax error I
don't think that'd be any big deal.

Anyway, thank you again, Jon.  Your explanation and model has greatly
cleared up my confusion, and I think if the docs reasoned along the same
lines it would clear up confusion in most programmers.  Certainly it
appears your line of reasoning is what Guido had in mind when he added
the else block.

Sorry Steven, I think Jon's right in this instance and your reasoning
isn't persuasive.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: replacing `else` with `then` in `for` and `try`

2017-11-03 Thread Ian Kelly
On Fri, Nov 3, 2017 at 8:32 AM, Chris Angelico  wrote:
> On Fri, Nov 3, 2017 at 10:49 PM, Jon Ribbens  
> wrote:
>> On 2017-11-03, Steve D'Aprano  wrote:
>>> On Fri, 3 Nov 2017 03:31 am, Jon Ribbens wrote:
 No, it's an obvious bug. You have a 'for...else' with no 'break'.
 Like I said, that should probably be a syntax error.
>>>
>>> It should absolutely not be a syntax error. There's no reason for it
>>> to be a syntax error, except to satisfy some arrogant and foolish
>>> idea of purity.
>>
>> It'd be nice if you could be a little less rude. It's not an "arrogant
>> and foolish idea of purity", it's to help people catch bugs in their
>> code, and to aid their understanding of the language.
>
> That wasn't rudeness. That was an accurate description of the
> situation. It is entirely possible for code to be opinionated,
> arrogant, foolish, and all those other adjectives that we normally
> appropriate to people.

Steve was clearly referring to the coder, not the code. Please stop
defending the use of incivility on this list.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: replacing `else` with `then` in `for` and `try`

2017-11-03 Thread Jon Ribbens
On 2017-11-03, Steve D'Aprano  wrote:
> The for loop does not necessarily perform a search:
>
> count = 1
> for obj in sequence:
> if count > MAX_OBJECTS:
> print("too many objects, halting")
> break
> process(obj)
> else:
> print("finished")
>
> According to your mental model, this code is... what? Illegal? Silly?
> Impossible? A syntax error?

That conforms to my model. It's searching for the condition
'count > MAX_OBJECTS'.

> Even when there is a search, the sense of the search may be reversed
> from your mental model:
>
> for request in sequence:
> if 'please' not in request:
> break
> process(request)
> else:
> print('done')
> return
> raise SysExit('failure to say please')

That's searching for the condition "'please' not in request".

> It doesn't matter if you can think of alternative ways of writing these code
> snippets. They're legal, and they work, and your mental model doesn't cover
> them, at all or easily. That means your mental model is at best incomplete.

You've yet to come up with one that it doesn't cover.

> In other words, it was only when I realised that `else` would be better
> written as `then` that I understood the behaviour of the statement. If I read
> it as "else", then the natural interpretation is that the block runs only if
> the loop doesn't run:

You're repeating yourself.

> You'll probably dismiss them as "silly" because they don't meet your mental
> model, and insist that I would be wrong to use them.

As above, you're mistaken.

> Your response to code that doesn't match your mental model is to say
> that it is obviously wrong and probably buggy and should be made
> into a syntax error if possible.

No, it isn't. Try reading again what I actually wrote.

> And my mental model is to treat "else" in this concept as some foreign word,
> perhaps Dutch, a false-friend that actually means "next" but due to some
> awful coincidence happens to look exactly like the English word for "else".

And that's leading you into confusion, as you've demonstrated.

> Ah yes, because it is inconceivable that anyone might have thought of a use
> for for...else without a break.

It's not inconceivable, but nobody has thought of a sensible use so far
(by which I mean one that shows it's a useful feature).

> What matters is that only code that matches your model is allowed.

You do seem to enjoy telling other people what their opinions are.
Frankly, I don't know why I even bother having opinions when you're
here to tell me what they are. In future, I'll just come to you to
find out what I think.

>> It's an incredibly obscure work-around for a different problem,
>
> You mean a different problem to "searching"? Yes indeed it is.

No, I mean a problem that has nothing to do with 'for...else' clauses.
If your door is stuck then you might climb in through a window, but
that doesn't mean that the purpose of windows is to be entrances,
or that windows should be designed to make them better entrances,
or that the problem isn't the stuck door.

>>> And while I thank you for the complement that I am the cleverest and most
>>> insightful Python coder in the world,
>> 
>> I didn't say anything even remotely resembling that.
>
> That was sarcasm.

Yes dear.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: replacing `else` with `then` in `for` and `try`

2017-11-03 Thread Jon Ribbens
On 2017-11-03, Chris Angelico  wrote:
> On Fri, Nov 3, 2017 at 10:49 PM, Jon Ribbens  
> wrote:
>>> It should absolutely not be a syntax error. There's no reason for it
>>> to be a syntax error, except to satisfy some arrogant and foolish
>>> idea of purity.
>>
>> It'd be nice if you could be a little less rude. It's not an "arrogant
>> and foolish idea of purity", it's to help people catch bugs in their
>> code, and to aid their understanding of the language.
>
> That wasn't rudeness.

Yes, it was.

>> No. Ok, so look. It's obvious that you and I have different mental
>> models of the situation here. You're thinking of 'for...else' as two
>> arbitrary clauses that run consecutively unless the whole thing is
>> aborted by a 'break', whereas I'm thinking of the 'for' clause as
>> being a search for a situation that matches a condition and the
>> 'else' clause being what happens if the condition is not matched
>> (i.e. exactly the same as 'if...else').
>>
>> Now there's nothing inherently *wrong* with your choice of mental
>> model, except it's leading you into confusion because my model means
>> the meaning of the 'else' keyword is intuitive and obvious, and yours
>> means it's counter-intuitive and confusing. Your suggestion is that
>> the fix is to change the language, my suggestion is to fix your model.
>> I'd suggest that changing your mind is easier than changing the
>> language ;-)
>
> If anything, I would say that Steven's model is at a lower abstraction
> layer than yours

Yes, absolutely.

> - though IMO your model is more of an example use-case than a
> description of what is actually happening.

It's a high-level way of thinking about it that avoids confusion and
leads to correct code. Unless you can come up with a *sensible*
use-case that it doesn't cover, it's also a comprehensive way of
thinking about it.

> TBH I prefer the "if 1:" trick to gather code into a block. But that
> requires pre-planning,

Or pressing up-arrow ;-)

> whereas slapping an "else:" after the loop can be done after the event.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: replacing `else` with `then` in `for` and `try`

2017-11-03 Thread Steve D'Aprano
On Fri, 3 Nov 2017 10:49 pm, Jon Ribbens wrote:

> On 2017-11-03, Steve D'Aprano  wrote:
>> On Fri, 3 Nov 2017 03:31 am, Jon Ribbens wrote:
>>> No, it's an obvious bug. You have a 'for...else' with no 'break'.
>>> Like I said, that should probably be a syntax error.
>>
>> It should absolutely not be a syntax error. There's no reason for it
>> to be a syntax error, except to satisfy some arrogant and foolish
>> idea of purity.
> 
> It'd be nice if you could be a little less rude. 

How else should we respond to the idea that something that has been legal
syntax for over twenty years and is in no way an error should be treated as a
syntax error, just to satisfy the opinion that nobody should write for...else
unless they are performing a search and it contains a break?


>> There are uncountable ways of writing code which is seemingly
>> "pointless", and we don't make it a syntax error.
> 
> And there's uncountable ways of writing code which we *do* make a
> syntax error. I'm not sure what your point is there.

None of these are syntax errors:

if False: do_something()

for x in '': pass

if True: pass

and uncountable other pieces of code which are, from some perspective,
pointless. We don't make them syntax errors because *pointless* doesn't imply
is is an error.

You think that a for...else loop with no break is pointless and "silly", even
when I demonstrate an actual use for it. Too bad. Even if it is "silly", in
your opinion, that still does not make it an error.

Is my point clear now?


>>> No, 'then' describes the opposite of what it does. The word 'then'
>>> implies something that always happens next,
>>
>> Right, which is what happens with the for...else block.
> 
> No.

Yes. It is not a matter of opinion that the `else` clause executes after
execution falls out the bottom of the loop, i.e. the loop runs, THEN the
`else` block runs.

It is an objective fact that in the absence of something which causes
execution to jump outside of the loop altogether (a return, a raise, or a
break) the execution order is loop first, then `else` block.

Both of these two sentences makes sense in English:

"Execution reaches the end of the loop, and THEN the `else` block runs."

"Execution reaches the end of the loop, or ELSE the `else` block runs."

but only the first describes what Python's for...else statement actually does.

This is not just my mental model, it is the actual objective behaviour of the
for...else statement.


> Ok, so look. It's obvious that you and I have different mental 
> models of the situation here. You're thinking of 'for...else' as two
> arbitrary clauses that run consecutively 

Scrub out the "arbitrary", and that is exactly what they are. They aren't
arbitrary: the `else` is optional, but if present it must follow after the
loop, and never the other way around.

The code inside the blocks can, of course, be any legal code we like. There's
no rule that says "only code approved by Jon Ribbens' is allowed", and
there's no rule that says "only searches are allowed".


> unless the whole thing is aborted by a 'break', 

Or return, raise, os._exit, os.abort, or having the process killed by the OS.
For simplicity we can ignore the last three (as well as more exotic
mechanisms such as "pull the power supply out" or "drop a two-tonne weight on
the computer"), but return and raise are common ways of exiting a loop and
should not be ignored or forgotten.


> whereas I'm thinking of the 'for' clause as 
> being a search for a situation that matches a condition and the
> 'else' clause being what happens if the condition is not matched
> (i.e. exactly the same as 'if...else').

That model conflates one specific use-case for the for...else statement with
the semantics of the statement, rather like insisting that "print displays a
greeting to the world" merely because 'print("Hello, World")' is so common.

The for loop does not necessarily perform a search:


count = 1
for obj in sequence:
if count > MAX_OBJECTS:
print("too many objects, halting")
break
process(obj)
else:
print("finished")


According to your mental model, this code is... what? Illegal? Silly?
Impossible? A syntax error?

Obviously wrong and almost certainly buggy?

Even when there is a search, the sense of the search may be reversed from your
mental model:


for request in sequence:
if 'please' not in request:
break
process(request)
else:
print('done')
return
raise SysExit('failure to say please')


It doesn't matter if you can think of alternative ways of writing these code
snippets. They're legal, and they work, and your mental model doesn't cover
them, at all or easily. That means your mental model is at best incomplete.

This is what happens when you treat one use-case for a general purpose
statement as synonymous with the statement itself. `for...else` is not just
for searching, and the `else` clause doesn't necessarily run if the search is
unsuccessful.

You've trapped yourself i

Re: replacing `else` with `then` in `for` and `try`

2017-11-03 Thread Chris Angelico
On Sat, Nov 4, 2017 at 3:15 AM, Alexey Muranov  wrote:
> On Fri, 2017-11-03 at 22:03 +1100, Chris Angelico wrote:
>> On Fri, Nov 3, 2017 at 8:48 PM, Alexey Muranov > com> wrote:
>> > 'Then' describes what happens next indeed, unless some
>> > extraordinary
>> > situation prevents it from happening, for example:
>> >
>> > try:
>> > go_to_the_bakery()
>> > then:
>> > buy_croissants(2)
>> > except BakeryClosed:
>> > go_to_the_grociery()
>> > buy_baguette(1)
>> > finally:
>> > come_back()
>> >
>> > I know this is a poor program example (why not to use a boolean
>> > return value
>> > instead of an exception, etc.), and i know that currently in Python
>> > `except`
>> > must precede `else`, it is just to illustrate the choice of terms.
>>
>> What is the semantic difference between that code and the same
>> without the "then:"?
>
> Chris,
>
> the semantic difference is that their meanings/behaviours are not identical
> (i imply that `then` here does what `else` currently does).  I agree however
> that from practical viewpoint the difference will probably never be
> observable (unless the person enters the bakery and asks for croissants, but
> during this time the baker exits the bakery and closes it to go on
> vacation).

Okay, so what you're doing is taking the current "try/else" semantics,
and hoisting the "happy path" up to immediately underneath the part
guarded by the try. That's not unreasonable, but also not a huge
advantage. It's basically saying:

try:
do_stuff
except None: # let's pretend
print("all is well")
except ValueError:
print("do_stuff has the wrong value")
finally:
print("we're done")

But if the difference between this and the current layout (with "else"
coming *after* the except blocks) is significant to you, I would
recommend refactoring the try/finally into a context manager:

with car_trip() as trip:
try:
trip.goto(bakery)
buy_croissants(2)
except BakeryClosed:
trip.goto(grocery)
buy_baguette(1)

The context manager takes care of bringing us home unconditionally,
leaving us with cleaner logic.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: replacing `else` with `then` in `for` and `try`

2017-11-03 Thread Alexey Muranov

On Fri, 2017-11-03 at 22:03 +1100, Chris Angelico wrote:
> On Fri, Nov 3, 2017 at 8:48 PM, Alexey Muranov  com> wrote:
> > 'Then' describes what happens next indeed, unless some
> > extraordinary
> > situation prevents it from happening, for example:
> >
> > try:
> > go_to_the_bakery()
> > then:
> > buy_croissants(2)
> > except BakeryClosed:
> > go_to_the_grociery()
> > buy_baguette(1)
> > finally:
> > come_back()
> >
> > I know this is a poor program example (why not to use a boolean
> > return value
> > instead of an exception, etc.), and i know that currently in Python
> > `except`
> > must precede `else`, it is just to illustrate the choice of terms.
>
> What is the semantic difference between that code and the same
> without the "then:"?

Chris,

the semantic difference is that their meanings/behaviours are not 
identical (i imply that `then` here does what `else` currently does).  
I agree however that from practical viewpoint the difference will 
probably never be observable (unless the person enters the bakery and 
asks for croissants, but during this time the baker exits the bakery 
and closes it to go on vacation).


I can try to think of a better example if you give me any good use-case 
for `else` in `try`.  I have searched on-line, and on StackOverflow in 
particular, but didn't find anything better that this:


 * https://stackoverflow.com/a/6051978

People seem very shy when it comes to giving a real-life example of 
`else` in `try`.


Alexey.

--
https://mail.python.org/mailman/listinfo/python-list


Re: replacing `else` with `then` in `for` and `try`

2017-11-03 Thread Chris Angelico
On Fri, Nov 3, 2017 at 10:49 PM, Jon Ribbens  wrote:
> On 2017-11-03, Steve D'Aprano  wrote:
>> On Fri, 3 Nov 2017 03:31 am, Jon Ribbens wrote:
>>> No, it's an obvious bug. You have a 'for...else' with no 'break'.
>>> Like I said, that should probably be a syntax error.
>>
>> It should absolutely not be a syntax error. There's no reason for it
>> to be a syntax error, except to satisfy some arrogant and foolish
>> idea of purity.
>
> It'd be nice if you could be a little less rude. It's not an "arrogant
> and foolish idea of purity", it's to help people catch bugs in their
> code, and to aid their understanding of the language.

That wasn't rudeness. That was an accurate description of the
situation. It is entirely possible for code to be opinionated,
arrogant, foolish, and all those other adjectives that we normally
appropriate to people.

I don't think it would do much for comprehension. And if it's to catch
bugs, that is NOT the job of syntax - it's the job of linters. By all
means, have a linter that says "else clause after loop with no break";
but don't make it *illegal*.

>> There are uncountable ways of writing code which is seemingly
>> "pointless", and we don't make it a syntax error.
>
> And there's uncountable ways of writing code which we *do* make a
> syntax error. I'm not sure what your point is there.

The point is that syntax errors are for things that cannot possibly
make sense, not for things that are likely to be bugs.

There are a very few exceptions, and they're usually things that are
massive bug magnets, or where the semantics are subtly different. And
I can't think of any examples right now other than the way "async def"
forces a function to be a coroutine even if it has no "await"s in it;
note that it does *not* make a syntax error, it simply causes the
semantics to be correct anyway.

>>> No, 'then' describes the opposite of what it does. The word 'then'
>>> implies something that always happens next,
>>
>> Right, which is what happens with the for...else block.
>
> No. Ok, so look. It's obvious that you and I have different mental
> models of the situation here. You're thinking of 'for...else' as two
> arbitrary clauses that run consecutively unless the whole thing is
> aborted by a 'break', whereas I'm thinking of the 'for' clause as
> being a search for a situation that matches a condition and the
> 'else' clause being what happens if the condition is not matched
> (i.e. exactly the same as 'if...else').
>
> Now there's nothing inherently *wrong* with your choice of mental
> model, except it's leading you into confusion because my model means
> the meaning of the 'else' keyword is intuitive and obvious, and yours
> means it's counter-intuitive and confusing. Your suggestion is that
> the fix is to change the language, my suggestion is to fix your model.
> I'd suggest that changing your mind is easier than changing the
> language ;-)

If anything, I would say that Steven's model is at a lower abstraction
layer than yours - though IMO your model is more of an example
use-case than a description of what is actually happening.

>>> Yes, I saw that. It's possible you are the only person in the world
>>> ever to have done that. It would not make the interactive interpreter
>>> 'worse' in the slightest for that silly trick to be lost.
>>
>> Just because you personally haven't used this technique doesn't make it
>> a "silly trick".
>
> It's an incredibly obscure work-around for a different problem,
> i.e. an infelicity in the way the interactive prompt parses input
> blocks. If the parsing is a genuine issue then the answer is to
> fix that, not to look for hacks that almost never help anyway.

TBH I prefer the "if 1:" trick to gather code into a block. But that
requires pre-planning, whereas slapping an "else:" after the loop can
be done after the event.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: replacing `else` with `then` in `for` and `try`

2017-11-03 Thread bartc

On 03/11/2017 11:49, Jon Ribbens wrote:

On 2017-11-03, Steve D'Aprano  wrote:



Right, which is what happens with the for...else block.


No. Ok, so look. It's obvious that you and I have different mental
models of the situation here. You're thinking of 'for...else' as two
arbitrary clauses that run consecutively unless the whole thing is
aborted by a 'break', whereas I'm thinking of the 'for' clause as
being a search for a situation that matches a condition and the
'else' clause being what happens if the condition is not matched
(i.e. exactly the same as 'if...else').

Now there's nothing inherently *wrong* with your choice of mental
model, except it's leading you into confusion because my model means
the meaning of the 'else' keyword is intuitive and obvious, and yours
means it's counter-intuitive and confusing. Your suggestion is that
the fix is to change the language, my suggestion is to fix your model.
I'd suggest that changing your mind is easier than changing the
language ;-)


I don't think there will be a short keyword that will suit everyone. It 
may be necessary to use this to spell out exactly how it works:


  for i in r:
 pass ...
  after_normal_loop_termination_then:
 pass ...

(And now, there is the possibility of having an additional 'else' clause 
to cover abnormal termination via break. This time what 'else' does is 
more obvious.)


--
bartc
--
https://mail.python.org/mailman/listinfo/python-list


Re: replacing `else` with `then` in `for` and `try`

2017-11-03 Thread Jon Ribbens
On 2017-11-03, Steve D'Aprano  wrote:
> On Fri, 3 Nov 2017 03:31 am, Jon Ribbens wrote:
>> No, it's an obvious bug. You have a 'for...else' with no 'break'.
>> Like I said, that should probably be a syntax error.
>
> It should absolutely not be a syntax error. There's no reason for it
> to be a syntax error, except to satisfy some arrogant and foolish
> idea of purity.

It'd be nice if you could be a little less rude. It's not an "arrogant
and foolish idea of purity", it's to help people catch bugs in their
code, and to aid their understanding of the language.

> There are uncountable ways of writing code which is seemingly
> "pointless", and we don't make it a syntax error.

And there's uncountable ways of writing code which we *do* make a
syntax error. I'm not sure what your point is there.

>> No, 'then' describes the opposite of what it does. The word 'then'
>> implies something that always happens next, 
>
> Right, which is what happens with the for...else block.

No. Ok, so look. It's obvious that you and I have different mental
models of the situation here. You're thinking of 'for...else' as two
arbitrary clauses that run consecutively unless the whole thing is
aborted by a 'break', whereas I'm thinking of the 'for' clause as
being a search for a situation that matches a condition and the
'else' clause being what happens if the condition is not matched
(i.e. exactly the same as 'if...else').

Now there's nothing inherently *wrong* with your choice of mental
model, except it's leading you into confusion because my model means
the meaning of the 'else' keyword is intuitive and obvious, and yours
means it's counter-intuitive and confusing. Your suggestion is that
the fix is to change the language, my suggestion is to fix your model.
I'd suggest that changing your mind is easier than changing the
language ;-)

Also, my model has the advantage that if what the 'for' clause is
doing doesn't match the concept of 'searching for a match' then it's
obvious that you shouldn't be using 'for...else' in the first place.
Again, sure, the language doesn't currently strictly enforce the
requirement for a 'break', but nevertheless if you don't have one
you almost certainly have a bug.

>> Yes, I saw that. It's possible you are the only person in the world
>> ever to have done that. It would not make the interactive interpreter
>> 'worse' in the slightest for that silly trick to be lost.
>
> Just because you personally haven't used this technique doesn't make it
> a "silly trick".

It's an incredibly obscure work-around for a different problem,
i.e. an infelicity in the way the interactive prompt parses input
blocks. If the parsing is a genuine issue then the answer is to
fix that, not to look for hacks that almost never help anyway.

> And while I thank you for the complement that I am the cleverest and most
> insightful Python coder in the world,

I didn't say anything even remotely resembling that.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: replacing `else` with `then` in `for` and `try`

2017-11-03 Thread Jon Ribbens
On 2017-11-03, Alexey Muranov  wrote:
> 'Then' describes what happens next indeed, unless some extraordinary 
> situation prevents it from happening, for example:
>
> try:
> go_to_the_bakery()
> then:
> buy_croissants(2)
> except BakeryClosed:
> go_to_the_grociery()
> buy_baguette(1)
> finally:
> come_back()
>
> I know this is a poor program example (why not to use a boolean return 
> value instead of an exception, etc.), and i know that currently in 
> Python `except` must precede `else`, it is just to illustrate the 
> choice of terms.

It looks like you're suggesting not just changing the 'else' keyword
to 'then', but changing the syntax completely. The above is certainly
not an improvement on the status quo, as it is completely
counter-intuitive that exceptions in the 'then' clause will not be
caught by the 'except' clauses.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: replacing `else` with `then` in `for` and `try`

2017-11-03 Thread Chris Angelico
On Fri, Nov 3, 2017 at 8:48 PM, Alexey Muranov  wrote:
> 'Then' describes what happens next indeed, unless some extraordinary
> situation prevents it from happening, for example:
>
>try:
>go_to_the_bakery()
>then:
>buy_croissants(2)
>except BakeryClosed:
>go_to_the_grociery()
>buy_baguette(1)
>finally:
>come_back()
>
> I know this is a poor program example (why not to use a boolean return value
> instead of an exception, etc.), and i know that currently in Python `except`
> must precede `else`, it is just to illustrate the choice of terms.

What is the semantic difference between that code and the same without
the "then:"? The normal behaviour of both Python code and human
instruction sheets is to proceed to the next instruction if nothing
went wrong:

1. Go to the office.
2. Sit down at the desk.
3. Open the third drawer down at your right hand.
4. Take the secret instructions.
5. Read and follow the instructions.
-- if something goes wrong, take out your pistol and kill every zombie
you find --

If there's no desk in the office, you won't continue to the next
steps. But for the normal case, you don't have to say "then".

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: replacing `else` with `then` in `for` and `try`

2017-11-03 Thread Alexey Muranov

On Thu, 2017-11-02 at 16:31 +, Jon Ribbens wrote:

> On 2017-11-02, Steve D'Aprano  wrote:

> > On Fri, 3 Nov 2017 12:39 am, Jon Ribbens wrote:

> > > Why would we want to make the language worse? It is fairly
> > > obvious
> > > what 'else' means,

> >
> > Yes, obvious and WRONG.

>
> Nope, obvious and right.
>


I suppose that to continue this way we'd need at some point define 
somehow the meaning of "obvious."





> > > whereas 'then' has an obvious meaning that is in
> > > fact the opposite of what it would actually do.

> >
> > Er... is today opposite day? Because 'then' describes precisely
> > what it
> > actually does.

>
> No, 'then' describes the opposite of what it does. The word 'then'
> implies something that always happens next, whereas 'else' conveys
> the correct meaning, which is something that happens if the course
> of the preceding piece of code did not go as expected.
>


Jon, i get from this that for you, when there is no exception in `try`, 
or no `break` in a loop, the things did not go as expected.  Either we 
need to agree that what is "expected" is subjective, or agree on some 
kind of formal or informal common meaning for it, because i would not 
have put it this way.


'Then' describes what happens next indeed, unless some extraordinary 
situation prevents it from happening, for example:


   try:
   go_to_the_bakery()
   then:
   buy_croissants(2)
   except BakeryClosed:
   go_to_the_grociery()
   buy_baguette(1)
   finally:
   come_back()

I know this is a poor program example (why not to use a boolean return 
value instead of an exception, etc.), and i know that currently in 
Python `except` must precede `else`, it is just to illustrate the 
choice of terms.


Best regards,

Alexey.

--
https://mail.python.org/mailman/listinfo/python-list


Re: replacing `else` with `then` in `for` and `try`

2017-11-02 Thread Steve D'Aprano
On Fri, 3 Nov 2017 03:31 am, Jon Ribbens wrote:

> On 2017-11-02, Steve D'Aprano  wrote:
>> On Fri, 3 Nov 2017 12:39 am, Jon Ribbens wrote:
>>> Why would we want to make the language worse? It is fairly obvious
>>> what 'else' means,
>>
>> Yes, obvious and WRONG.
> 
> Nope, obvious and right.
>
>> for x in seq:
>> do_something()
>> else:
>> print("seq was empty")
>>
>> is an obvious, common and wrong interpretation.
> 
> No, it's an obvious bug. You have a 'for...else' with no 'break'.
> Like I said, that should probably be a syntax error.

It should absolutely not be a syntax error. There's no reason for it to be a
syntax error, except to satisfy some arrogant and foolish idea of purity.

There are uncountable ways of writing code which is seemingly "pointless", and
we don't make it a syntax error. Sometimes it is even useful. A for...else
with no break should no more be a syntax error than "if True".


>>> whereas 'then' has an obvious meaning that is in
>>> fact the opposite of what it would actually do.
>>
>> Er... is today opposite day? Because 'then' describes precisely what it
>> actually does.
> 
> No, 'then' describes the opposite of what it does. The word 'then'
> implies something that always happens next, 

Right, which is what happens with the for...else block.

The else block is executed after the for loop, unless you jump out of the
statement using return, raise or break. The flow is:

# this is what actually happens
loop
then `else` block

rather than:

# this is incorrect
loop
else (otherwise) `else` block

which implies that that `else` block runs if the loop did not.


> whereas 'else' conveys 
> the correct meaning, which is something that happens if the course
> of the preceding piece of code did not go as expected.

That's not what happens. This is WRONG:

for x in sequence:
...
else:
print("something unexpected happened")


Apart from the impossibility of deciding what "unexpected" means in general,
the behaviour is the opposite. The `else` clause executes immediately after
you fall out the bottom of the for-loop, NOT conditional on some event
(whether unexpected or not).


>>> Maybe the change should be that it is a syntax error to use a
>>> 'for/while...else' with no 'break'.
>>
>> Only if you want to make the experience of using Python in the interactive
>> interpreter worse. See my recent post:
>>
>> "A use-case for for...else with no break"
> 
> Yes, I saw that. It's possible you are the only person in the world
> ever to have done that. It would not make the interactive interpreter
> 'worse' in the slightest for that silly trick to be lost.

Just because you personally haven't used this technique doesn't make it
a "silly trick".

And while I thank you for the complement that I am the cleverest and most
insightful Python coder in the world, I'm sure I'm not. If I could think of
this technique, I daresay that many other people who are much smarter than me
have done so too.



-- 
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: replacing `else` with `then` in `for` and `try`

2017-11-02 Thread Wolfgang Maier

On 11/02/2017 06:09 PM, Skip Montanaro wrote:

Eh, what can I say? I guess I was paying too much attention to the baseball
game. Yes, "else" handles the "fall off the end" termination, not the "exit
early" termination. My apologies. I do think that having a way to spell "do
this when the loop exits early" makes things clearer. So, perhaps while and
for loops could someday grow except clauses. :-)



... and even this idea has been discussed before:

https://mail.python.org/pipermail/python-ideas/2017-March/044932.html

There wasn't much enthusiasm about it though because few people (ok, 
maybe even just me) thought it had interesting use cases.


--
https://mail.python.org/mailman/listinfo/python-list


Re: replacing `else` with `then` in `for` and `try`

2017-11-02 Thread Skip Montanaro
Eh, what can I say? I guess I was paying too much attention to the baseball
game. Yes, "else" handles the "fall off the end" termination, not the "exit
early" termination. My apologies. I do think that having a way to spell "do
this when the loop exits early" makes things clearer. So, perhaps while and
for loops could someday grow except clauses. :-)


On Thu, Nov 2, 2017 at 5:04 AM, Steve D'Aprano 
wrote:

> On Thu, 2 Nov 2017 12:49 pm, Skip Montanaro wrote:
>
> > I don't know. The word "then" doesn't connote different ways of exiting a
> > loop to me ("else" doesn't really either, I will grant you that, but it's
> > what we have). Here's how I would read things:
> >
> >- *while* some condition holds, execute the loop, possibly breaking
> out,
> >*then* do some finishing work
> >- *for* each element in some sequence, execute the loop, possibly
> >breaking out, *then* do some finishing work
>
> And that is exactly the behaviour of the for...else and while...else
> construct. You're reading it correctly.
>
> When you say "possibly breaking out", I assume you mean breaking out of the
> *entire* compound statement, because the alternative would be just silly.
> The
> alternative would be exactly equivalent to just following the loop with
> some
> unindented code:
>
>
> while condition:
> block
> # on break we jump to here
> finishing
>
>
> In that case, it makes no sense to include a do-nothing "else" or "then"
> keyword.
>
> To put it another way, if we are trying to infer the semantics of a
> statement,
> and can interpret it in one of two ways:
>
> - it does something
>
> - it does nothing
>
> then (with special case) of `pass`, we should always assume the first case,
> thus resolving the ambiguity in favour of "Guido isn't an idiot who added a
> pointless keyword" :-)
>
>
> > In neither case does it seem to me that you execute the finishing work
> only
> > if you break out of the loop, but not if the loop terminates when the
> while
> > condition becomes false or the for loop's sequence is exhausted.
>
> If I'm reading you correctly, I think you are confused about the `else`
> clause. It is incorrect to say that the `else` clause runs "only if you
> break
> out of the loop" (as you say). The `else` clause runs *after* the loop
> completes, but NOT if you jump out with break/return/raise.
>
> If we don't jump out of the loop, the else block is equivalent to just
> following the loop with unindented code:
>
>
> for x in sequence:
> block
> else:
> follows
>
>
> is equivalent to:
>
>
> for x in sequence:
> block
> follows
>
>
> Hence, in the absence of any early exit from the loop, the `else` block
> behaves more like an *then* rather than an "else". The behaviour of `else`
> confused me utterly until I realised that the semantics of the compound
> for...else was the loop to execute, then the `else` block.
>
> So why even bother with `else`?
>
> Unlike the second case, the `else` block is part for the compound for/while
> statement. And so `break` doesn't just exit the loop, it exits the whole
> compound statement, jumping past the `else`:
>
> for x in sequence:
> block
> else:
> follows
> # break jumps to here
> more code
>
>
> The motive for allowing this pattern is described here:
>
> https://shahriar.svbtle.com/pythons-else-clause-in-loops
>
>
> > You might
> > consider that while/then or for/then actually reads too much like
> English,
> > fooling you into interpreting it as English, opening you up to ambiguity.
>
> If you interpret it as English, it works fine. You run the loop, then you
> run
> the "then" clause. If you jump out of the loop (whether by return, raise or
> break) you jump out of the *entire* statement, not just the loop part.
>
> There's no ambiguity because we can assume Guido wouldn't introduce a
> pointless block keyword that does literally nothing except require an
> indent.
>
>
> > You might argue that "else" doesn't either, but it has the strangely nice
> > property of actually being a bit clumsier to read, forcing the reader to
> > learn and apply the precise rules of the programming language instead of
> > infer the more ambiguous rules of English.
>
> If only that were true...
>
> There's a simple, obvious, but sadly WRONG plain English interpretation of
> for...else, namely that the `else` clause runs if the for sequence was
> empty:
>
>
> for x in L:
> pass
> else:
> # This is wrong!
> print("L is empty")
>
>
> and similar for while. That lead me astray for the longest time! And I'm
> not
> the only one.
>
>
> > English and other natural languages aren't precise enough to serve as
> > programming languages.
>
> Hmmm... I think Hypertalk might have something to say about that.
>
> And Inform7 I think would laugh in your face :-)
>
>
>
>
> --
> 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
>
-- 
https:/

Re: replacing `else` with `then` in `for` and `try`

2017-11-02 Thread Jon Ribbens
On 2017-11-02, Steve D'Aprano  wrote:
> On Fri, 3 Nov 2017 12:39 am, Jon Ribbens wrote:
>> Why would we want to make the language worse? It is fairly obvious
>> what 'else' means, 
>
> Yes, obvious and WRONG.

Nope, obvious and right.

> for x in seq:
> do_something()
> else:
> print("seq was empty")
>
> is an obvious, common and wrong interpretation.

No, it's an obvious bug. You have a 'for...else' with no 'break'.
Like I said, that should probably be a syntax error.

>> whereas 'then' has an obvious meaning that is in 
>> fact the opposite of what it would actually do.
>
> Er... is today opposite day? Because 'then' describes precisely what it
> actually does.

No, 'then' describes the opposite of what it does. The word 'then'
implies something that always happens next, whereas 'else' conveys
the correct meaning, which is something that happens if the course
of the preceding piece of code did not go as expected.

> Perhaps before we continue, we should ask what you think for...else
> and while...else statements do. Just to be sure we are all on the
> same page here.

I think they do what the Python Language Reference sections 8.2
and 8.3 say they do.

>> It seems clear that 'else' is the correct word (or at least, far
>> better than 'then').
>
> Not clear at all. The 'for...else' block is a common source of
> confusion, if it was clear what it did, people wouldn't so often get
> it wrong.

That might be an argument that it is imperfect. It doesn't even begin
to constitute an argument that 'then' would be an improvement.

>> Maybe the change should be that it is a syntax error to use a
>> 'for/while...else' with no 'break'.
>
> Only if you want to make the experience of using Python in the interactive
> interpreter worse. See my recent post:
>
> "A use-case for for...else with no break"

Yes, I saw that. It's possible you are the only person in the world
ever to have done that. It would not make the interactive interpreter
'worse' in the slightest for that silly trick to be lost.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: replacing `else` with `then` in `for` and `try`

2017-11-02 Thread Steve D'Aprano
On Fri, 3 Nov 2017 12:39 am, Jon Ribbens wrote:

> On 2017-11-01, Alexey Muranov  wrote:
>> what do you think about the idea of replacing "`else`" with "`then`" in
>> the contexts of `for` and `try`?
>>
>> It seems clear that it should be rather "then" than "else."  Compare
>> also "try ... then ... finally" with "try ... else ... finally".
>>
>> Currently, with "else", it is almost impossible to guess the meaning
>> without looking into the documentation.
> 
> Why would we want to make the language worse? It is fairly obvious
> what 'else' means, 

Yes, obvious and WRONG.

for x in seq:
do_something()
else:
print("seq was empty")

is an obvious, common and wrong interpretation.


> whereas 'then' has an obvious meaning that is in 
> fact the opposite of what it would actually do.

Er... is today opposite day? Because 'then' describes precisely what it
actually does.

Perhaps before we continue, we should ask what you think for...else and
while...else statements do. Just to be sure we are all on the same page here.


> It seems clear that 
> 'else' is the correct word (or at least, far better than 'then').

Not clear at all. The 'for...else' block is a common source of confusion, if
it was clear what it did, people wouldn't so often get it wrong.


> Maybe the change should be that it is a syntax error to use a
> 'for/while...else' with no 'break'.

Only if you want to make the experience of using Python in the interactive
interpreter worse. See my recent post:

"A use-case for for...else with no break"



-- 
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: replacing `else` with `then` in `for` and `try`

2017-11-02 Thread breamoreboy
On Wednesday, November 1, 2017 at 9:14:05 PM UTC, Alexey Muranov wrote:
> Hello,
> 
> what do you think about the idea of replacing "`else`" with "`then`" in 
> the contexts of `for` and `try`?
> 
> It seems clear that it should be rather "then" than "else."  Compare 
> also "try ... then ... finally" with "try ... else ... finally".
> 
> Currently, with "else", it is almost impossible to guess the meaning 
> without looking into the documentation.
> 
> Off course, it should not be changed in Python 3, maybe in Python 4 or 
> 5, but in Python 3 `then` could be an alias of `else` in these contexts.
> 
> Alexey.

It has been discussed before.  I believe the chances of it ever happening are 
roughly zero.

There's a good write up on the subject here 
http://python-notes.curiousefficiency.org/en/latest/python_concepts/break_else.html

--
My fellow Pythonistas, ask not what our language can do for you, ask
what you can do for our language.

Mark Lawrence
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: replacing `else` with `then` in `for` and `try`

2017-11-02 Thread Jon Ribbens
On 2017-11-01, Alexey Muranov  wrote:
> what do you think about the idea of replacing "`else`" with "`then`" in 
> the contexts of `for` and `try`?
>
> It seems clear that it should be rather "then" than "else."  Compare 
> also "try ... then ... finally" with "try ... else ... finally".
>
> Currently, with "else", it is almost impossible to guess the meaning 
> without looking into the documentation.

Why would we want to make the language worse? It is fairly obvious
what 'else' means, whereas 'then' has an obvious meaning that is in
fact the opposite of what it would actually do. It seems clear that
'else' is the correct word (or at least, far better than 'then').

Maybe the change should be that it is a syntax error to use a
'for/while...else' with no 'break'.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: replacing `else` with `then` in `for` and `try`

2017-11-02 Thread Jerry Hill
On Wed, Nov 1, 2017 at 5:12 PM, Alexey Muranov 
wrote:

> what do you think about the idea of replacing "`else`" with "`then`" in
> the contexts of `for` and `try`?
>

​I wish the core python developers​ had done it 20 years ago.  Given that
python is a relatively mature language at this point, I don't expect that
it will ever change.

-- 
Jerry
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: replacing `else` with `then` in `for` and `try`

2017-11-02 Thread Ben Bacarisse
Steve D'Aprano  writes:

> On Thu, 2 Nov 2017 10:09 pm, Ben Bacarisse wrote:
>
>> Sure, but your argument seemed to that else has entirely the wrong
>> meaning (I certainly to a double take when I have to remember what it
>> means) and, in that context, finally has a meaning closer to what you
>> want.
>
> That's an argument about whether "yellow" or "purple" is closer in meaning to
> the word we actually want, "spicy" :-)

I note the smiley, but it was in fact an argument that "finally" is
closer to "and afterwards" than "else" is :-)

-- 
Ben.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: replacing `else` with `then` in `for` and `try`

2017-11-02 Thread Steve D'Aprano
On Thu, 2 Nov 2017 10:09 pm, Ben Bacarisse wrote:

> Sure, but your argument seemed to that else has entirely the wrong
> meaning (I certainly to a double take when I have to remember what it
> means) and, in that context, finally has a meaning closer to what you
> want.

That's an argument about whether "yellow" or "purple" is closer in meaning to
the word we actually want, "spicy" :-)



-- 
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: replacing `else` with `then` in `for` and `try`

2017-11-02 Thread Ben Bacarisse
Steve D'Aprano  writes:

> On Thu, 2 Nov 2017 12:50 pm, Ben Bacarisse wrote:
>
>> Steve D'Aprano  writes:
>> 
>>> On Thu, 2 Nov 2017 08:12 am, Alexey Muranov wrote:
>>>
 what do you think about the idea of replacing "`else`" with "`then`" in
 the contexts of `for` and `try`?
> [...]
>> Re-using finally would not need a new keyword and might be close enough
>> in meaning.
>
> Reusing finally would be *completely* wrong.
>
> The semantics of `finally` is that it should be executed no matter[1] how you
> exit the previous block. E.g. if we write:
>
>
> try:
> return 1
> finally:
> print("exiting")
>
>
> then "exiting" is printed. Replace the return with a raise, and the same
> applies. Reusing `finally` in for and while loops would imply the similar
> behaviour:
>
>
> for i in range(100):
> return i
> finally:
> print("exiting")
>
>
> should print "exiting", when in fact it does not. Likewise if you replace the
> return with a break.

Sure, but your argument seemed to that else has entirely the wrong
meaning (I certainly to a double take when I have to remember what it
means) and, in that context, finally has a meaning closer to what you
want.  The problem that it carries different meanings when added to
different statements is already the case with else -- it's an
alternative to an if and not an alternative to a loop.


-- 
Ben.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: replacing `else` with `then` in `for` and `try`

2017-11-02 Thread Steve D'Aprano
On Thu, 2 Nov 2017 09:04 pm, Steve D'Aprano wrote:

> then (with special case) of `pass`

That should read "then except for the special case of `pass`".

Sorry.


-- 
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: replacing `else` with `then` in `for` and `try`

2017-11-02 Thread Steve D'Aprano
On Thu, 2 Nov 2017 12:49 pm, Skip Montanaro wrote:

> I don't know. The word "then" doesn't connote different ways of exiting a
> loop to me ("else" doesn't really either, I will grant you that, but it's
> what we have). Here's how I would read things:
> 
>- *while* some condition holds, execute the loop, possibly breaking out,
>*then* do some finishing work
>- *for* each element in some sequence, execute the loop, possibly
>breaking out, *then* do some finishing work

And that is exactly the behaviour of the for...else and while...else
construct. You're reading it correctly.

When you say "possibly breaking out", I assume you mean breaking out of the
*entire* compound statement, because the alternative would be just silly. The
alternative would be exactly equivalent to just following the loop with some
unindented code:


while condition:
block
# on break we jump to here
finishing


In that case, it makes no sense to include a do-nothing "else" or "then"
keyword.

To put it another way, if we are trying to infer the semantics of a statement,
and can interpret it in one of two ways:

- it does something

- it does nothing

then (with special case) of `pass`, we should always assume the first case,
thus resolving the ambiguity in favour of "Guido isn't an idiot who added a
pointless keyword" :-)


> In neither case does it seem to me that you execute the finishing work only
> if you break out of the loop, but not if the loop terminates when the while
> condition becomes false or the for loop's sequence is exhausted.

If I'm reading you correctly, I think you are confused about the `else`
clause. It is incorrect to say that the `else` clause runs "only if you break
out of the loop" (as you say). The `else` clause runs *after* the loop
completes, but NOT if you jump out with break/return/raise.

If we don't jump out of the loop, the else block is equivalent to just
following the loop with unindented code:


for x in sequence:
block
else:
follows


is equivalent to:


for x in sequence:
block
follows


Hence, in the absence of any early exit from the loop, the `else` block
behaves more like an *then* rather than an "else". The behaviour of `else`
confused me utterly until I realised that the semantics of the compound
for...else was the loop to execute, then the `else` block.

So why even bother with `else`?

Unlike the second case, the `else` block is part for the compound for/while
statement. And so `break` doesn't just exit the loop, it exits the whole
compound statement, jumping past the `else`:

for x in sequence:
block
else:
follows
# break jumps to here
more code

 
The motive for allowing this pattern is described here:

https://shahriar.svbtle.com/pythons-else-clause-in-loops


> You might
> consider that while/then or for/then actually reads too much like English,
> fooling you into interpreting it as English, opening you up to ambiguity.

If you interpret it as English, it works fine. You run the loop, then you run
the "then" clause. If you jump out of the loop (whether by return, raise or
break) you jump out of the *entire* statement, not just the loop part.

There's no ambiguity because we can assume Guido wouldn't introduce a
pointless block keyword that does literally nothing except require an indent.


> You might argue that "else" doesn't either, but it has the strangely nice
> property of actually being a bit clumsier to read, forcing the reader to
> learn and apply the precise rules of the programming language instead of
> infer the more ambiguous rules of English.

If only that were true... 

There's a simple, obvious, but sadly WRONG plain English interpretation of
for...else, namely that the `else` clause runs if the for sequence was empty:


for x in L:
pass
else:
# This is wrong!
print("L is empty")


and similar for while. That lead me astray for the longest time! And I'm not
the only one.


> English and other natural languages aren't precise enough to serve as
> programming languages. 

Hmmm... I think Hypertalk might have something to say about that.

And Inform7 I think would laugh in your face :-)




-- 
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: replacing `else` with `then` in `for` and `try`

2017-11-02 Thread Chris Angelico
On Thu, Nov 2, 2017 at 7:05 PM, Alexey Muranov  wrote:
> On Wed, 2017-11-01 at 21:30 +, Stefan Ram wrote:
>>
>> >
>> >   In languages like Algol 68, »then« is used for a clause
>> >   that is to be executed when the main condition of an
>> >   if-statement /is/ true, so this might cause some confusion.
>> >
>
>
> sure, and `else` is used for a clause that is to be executed when the main
> condition of `if` is false.
>
> So, in
>
>try:
>do_something
>except:
>catch_exception
>else:
>continue_doing_something
>
> when no exception occurs in `do_something`, is `do_something` more true, or
> more false?

It's neither. It didn't happen. That's the whole point of exceptions -
they aren't about normal flow and normal values, they are
fundamentally different. But if you like, consider this kind of model:

caught_exception = catch {{{
do_something
}}}
if caught_exception is not None:
handle_exception
else:
continue_doing_something

The caught exception is either a thing, or not a thing.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: replacing `else` with `then` in `for` and `try`

2017-11-02 Thread Alexey Muranov

On Thu, 2017-11-02 at 08:21 +1100, Chris Angelico wrote:

>
>
With try/except/else, it's "do this, and if an exception happens, do 
this, else do this". So else makes perfect sense.


Indeed, i forgot about `except`.  I agree that 
"try/then/except/finally" would be better than 
"try/except/then/finally", but "try/except/else/finally" does not make 
a perfect sense IMHO.


Alexey.

--
https://mail.python.org/mailman/listinfo/python-list


Re: replacing `else` with `then` in `for` and `try`

2017-11-02 Thread Terry Reedy

On 11/1/2017 5:12 PM, Alexey Muranov wrote:

what do you think about the idea of replacing "`else`" with "`then`" in 
the contexts of `for` and `try`?


This idea has been argued to death more than once before.  I am opposed 
on both logical and practical grounds, but will not repeat myself for 
the fourth or fifth time.


--
Terry Jan Reedy

--
https://mail.python.org/mailman/listinfo/python-list


Re: replacing `else` with `then` in `for` and `try`

2017-11-02 Thread Alexey Muranov

On Wed, 2017-11-01 at 21:30 +, Stefan Ram wrote:

>
>   In languages like Algol 68, »then« is used for a clause
>   that is to be executed when the main condition of an
>   if-statement /is/ true, so this might cause some confusion.
>


sure, and `else` is used for a clause that is to be executed when the 
main condition of `if` is false.


So, in

   try:
   do_something
   except:
   catch_exception
   else:
   continue_doing_something

when no exception occurs in `do_something`, is `do_something` more 
true, or more false?


Alexey.

--
https://mail.python.org/mailman/listinfo/python-list


Re: replacing `else` with `then` in `for` and `try`

2017-11-02 Thread Alexey Muranov

On Thu, 2017-11-02 at 08:29 +1100, Chris Angelico wrote:
> On Thu, Nov 2, 2017 at 8:23 AM, Ned Batchelder 

> > wrote:

> >
> >
> > Apart from the questions of backward compatibility etc (Python is
> > unlikely
> > to ever go through another shift like the 2/3 breakage), are you
> > sure "then"
> > is what you mean?  This won't print "end":
> >
> > for i in range(10):
> > print(i)
> > else:
> > print(end)

>
> Well, it'll bomb with NameError when it tries to look up the *name*
> end. But it will run that line of code - if you quote it, it will
> work.


You see how people are confused over "for ... else".

Alexey.

--
https://mail.python.org/mailman/listinfo/python-list


Re: replacing `else` with `then` in `for` and `try`

2017-11-02 Thread Chris Angelico
On Thu, Nov 2, 2017 at 12:42 PM, bartc  wrote:
> But if people prefer a different keyword, then why not? I think 'then' can
> be used, without impacting its use as an identifier, because it will always
> be followed by ":". Of course you would need to allow both "else" and "then"
> for backwards compatibility.

No, it can't. Contextually-sensitive keywords are a road to major
confusion. It's been done before, but usually (always?) as a migration
plan towards full keyword status; most recently, 'async' and 'await'
were brought in that way:

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():
...  pass
...
>>> async = 1
>>>


Python 3.7.0a2+ (heads/master:4f469c0966, Nov  2 2017, 18:04:12)
[GCC 6.3.0 20170516] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> async def foo():
...  pass
...
>>> async = 1
  File "", line 1
async = 1
  ^
SyntaxError: invalid syntax

>From Python 3.4 to Python 3.7, async changes from being an identifier
to being a keyword. The only reason it's a "soft keyword" for 3.5 and
3.6 is for the sake of transition - it's not a means of avoiding the
costs of keyword creation. The proposal for async functions had to
justify the creation of two keywords.

Additionally, the notion of having both "else" and "then" is even
worse: everyone has to learn BOTH keywords, and figure out when to use
each. For compatibility with older Python versions, most people will
use "else", but some will go with "then" because it's the new and
trendy option.

Ugh. I deal with this sort of thing in JavaScript. I don't want to
have it in Python too.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: replacing `else` with `then` in `for` and `try`

2017-11-01 Thread Steve D'Aprano
On Thu, 2 Nov 2017 12:50 pm, Ben Bacarisse wrote:

> Steve D'Aprano  writes:
> 
>> On Thu, 2 Nov 2017 08:12 am, Alexey Muranov wrote:
>>
>>> what do you think about the idea of replacing "`else`" with "`then`" in
>>> the contexts of `for` and `try`?
[...]
> Re-using finally would not need a new keyword and might be close enough
> in meaning.

Reusing finally would be *completely* wrong.

The semantics of `finally` is that it should be executed no matter[1] how you
exit the previous block. E.g. if we write:


try:
return 1
finally:
print("exiting")


then "exiting" is printed. Replace the return with a raise, and the same
applies. Reusing `finally` in for and while loops would imply the similar
behaviour:


for i in range(100):
return i
finally:
print("exiting")


should print "exiting", when in fact it does not. Likewise if you replace the
return with a break.





[1] Within the bounds of normal processing. There are ways to halt Python
without executing any subsequent code, namely os._exit, and os.abort dumps
core to exit immediately.


-- 
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: replacing `else` with `then` in `for` and `try`

2017-11-01 Thread Chris Angelico
On Thu, Nov 2, 2017 at 12:19 PM, Steve D'Aprano
 wrote:
> On Thu, 2 Nov 2017 08:21 am, Chris Angelico wrote:
>
>> With the 'for' loop,
>> it's a bit more arguable, but I've never seen anything more than a
>> weak argument in favour of 'then'
>
> Thhpptpt!
>
> "else" is an completely inappropriate term that doesn't describe the semantics
> of the statement even a little bit. The argument that it means "else no
> break" is feeble because break is not the only way to exit the loop and
> therefore skip executing the else clause.
>
> It is not even necessarily the most common: I wouldn't be surprised if there
> were more returns out of the middle of a loop than breaks, although I
> wouldn't necessarily predict it either.

I'd say that's plausible, partly because it's easier than messing
around with the else clause. Sometimes, it's easier to just make
another function so you can use 'return' as flow control.

> If we spoke in ordinary English using "else" the way Python uses it for
> looping, we would say:
>
> "Shampoo your hair twice, ELSE apply conditioner and leave for five minutes
> before rinsing."

You wouldn't use 'else' with a simple iteration loop like that -
there's no difference between 'else' and simply having more code after
the loop, unless you have a break.

for _ in range(2):
hair.shampoo()
condition()
sleep(300)

> "Boil the pasta until it is soft, ELSE drain it and mix in the sauce."

Except that the else keyword doesn't mean that. Here's the nearest I
can come up with as an equivalent:

while pot.water_level:
pasta.boil()
if pasta.is_soft(): break
else:
print("HELP! You boiled the pot dry!")

The else clause happens if you don't break. If you break, you skip the
rest of the loop - including the else. You could use "then" for this,
and it would make sense, but not enough to create a new keyword, and
DEFINITELY not enough to justify changing it now.

Yes, there are arguments against calling this feature "else". But I
stand by my assertion that there are none strong enough to justify a
new keyword.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: replacing `else` with `then` in `for` and `try`

2017-11-01 Thread Ben Bacarisse
Steve D'Aprano  writes:

> On Thu, 2 Nov 2017 08:12 am, Alexey Muranov wrote:
>
>> what do you think about the idea of replacing "`else`" with "`then`" in
>> the contexts of `for` and `try`?
>
> Yes, this, exactly!!!
>
> (For while and for loops, but not try -- see below.)
>
> I have argued this for many years. The current choice of "else" is painfully
> misleading, and it causes people (including myself) to wrongly guess that
> the "else" block runs only if the for/while block doesn't run at all:
>
>
> # This is wrong!
> for x in sequence:
> ...
> else:
> print("sequence is empty")
>
>
> The actually semantics of "else" is that the block is UNCONDITIONALLY run
> after the for/while loop completes, unless you jump out of the loop using
> return, raise or break. That makes it a "then" block, not "else".
>
>
>> It seems clear that it should be rather "then" than "else."  Compare
>> also "try ... then ... finally" with "try ... else ... finally".
>
> I disagree about the try block though. The semantics of the try block are:
>
> try:
>A
> except:
>B
> else:
>C
> finally:
>D
>
> (1) code block A is attempted;
>
> (2) IF an exception occurs, jump to code block B;
>
> (3) otherwise (else), no exception occurs, so jump to code block C;
>
> (4) finally run code block D on your way out, regardless of which blocks are
> executed and how you exit them.
>
>
> So I think "else" is correct here. The else block only gets called if there is
> no exception.
>
>
>> Currently, with "else", it is almost impossible to guess the meaning
>> without looking into the documentation.
>
> It is worse than that: it is easy to guess the WRONG meaning, namely that the
> else block runs when the for/while loop doesn't execute at all (the for-loop
> sequence is empty, or the while-loop condition is initially false).
>
>
>> Off course, it should not be changed in Python 3, maybe in Python 4 or
>> 5, but in Python 3 `then` could be an alias of `else` in these contexts.
>
> Unfortunately, this is almost certainly not going to happen. It would require
> adding a new keyword, and unless Guido changes his mind, he doesn't think
> this change is worthwhile.

Re-using finally would not need a new keyword and might be close enough
in meaning.


-- 
Ben.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: replacing `else` with `then` in `for` and `try`

2017-11-01 Thread Skip Montanaro
I don't know. The word "then" doesn't connote different ways of exiting a
loop to me ("else" doesn't really either, I will grant you that, but it's
what we have). Here's how I would read things:

   - *while* some condition holds, execute the loop, possibly breaking out,
   *then* do some finishing work
   - *for* each element in some sequence, execute the loop, possibly
   breaking out, *then* do some finishing work

In neither case does it seem to me that you execute the finishing work only
if you break out of the loop, but not if the loop terminates when the while
condition becomes false or the for loop's sequence is exhausted. You might
consider that while/then or for/then actually reads too much like English,
fooling you into interpreting it as English, opening you up to ambiguity.
You might argue that "else" doesn't either, but it has the strangely nice
property of actually being a bit clumsier to read, forcing the reader to
learn and apply the precise rules of the programming language instead of
infer the more ambiguous rules of English. Either way, we are down to two
imperfect solutions, and have a case of tomato, tomahto, I think.

If I was starting with a clean sheet of paper, I might put the raise and
except keywords to work, and add a LoopExit exception:

while some condition holds:
blah blah blah
if some other condition rears its ugly head:
raise LoopExit
blah blah blah
except LoopExit:
execute exceptional code

English and other natural languages aren't precise enough to serve as
programming languages. Neither are programming languages fluid enough that
we can always expect them to read naturally. There will always be cases
like this where there is no perfect solution. Other examples I can think of
are the if/else expression added to the language relatively recently (never
really reads well to me, though I agree it can be handy), or all the
proposals for switch/case/computed goto statements which litter the Python
PEP cemetery. The desire to add such a statement has been very strong at
times (there is a powerful desire from a performance perspective to have
something akin to C's switch statement), but nothing ever worked well
enough to be accepted.

Skip
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: replacing `else` with `then` in `for` and `try`

2017-11-01 Thread bartc

On 02/11/2017 01:06, Steve D'Aprano wrote:

On Thu, 2 Nov 2017 08:12 am, Alexey Muranov wrote:


Hello,

what do you think about the idea of replacing "`else`" with "`then`" in
the contexts of `for` and `try`?



Yes, this, exactly!!!

(For while and for loops, but not try -- see below.)

I have argued this for many years. The current choice of "else" is painfully
misleading, and it causes people (including myself) to wrongly guess that
the "else" block runs only if the for/while block doesn't run at all:


# This is wrong!
for x in sequence:
 ...
else:
 print("sequence is empty")


The actually semantics of "else" is that the block is UNCONDITIONALLY run
after the for/while loop completes,


/If/ it completes, and /when/ it completes. Otherwise why bother with 
using 'else'? Just have the code immediately following the loop.


And there are some circumstances where the 'else' part is never executed.

But if people prefer a different keyword, then why not? I think 'then' 
can be used, without impacting its use as an identifier, because it will 
always be followed by ":". Of course you would need to allow both "else" 
and "then" for backwards compatibility.


--
bartc
--
https://mail.python.org/mailman/listinfo/python-list


Re: replacing `else` with `then` in `for` and `try`

2017-11-01 Thread bartc

On 02/11/2017 01:19, Steve D'Aprano wrote:

On Thu, 2 Nov 2017 08:21 am, Chris Angelico wrote:


With the 'for' loop,
it's a bit more arguable, but I've never seen anything more than a
weak argument in favour of 'then'


Thhpptpt!

"else" is an completely inappropriate term that doesn't describe the semantics
of the statement even a little bit. The argument that it means "else no
break" is feeble because break is not the only way to exit the loop and
therefore skip executing the else clause.

It is not even necessarily the most common: I wouldn't be surprised if there
were more returns out of the middle of a loop than breaks, although I
wouldn't necessarily predict it either.

If we spoke in ordinary English using "else" the way Python uses it for
looping, we would say:

"Shampoo your hair twice, ELSE apply conditioner and leave for five minutes
before rinsing."

"Boil the pasta until it is soft, ELSE drain it and mix in the sauce."


1 Start boiling the pasta
2 Wait one minute
3 If it's not soft (some of us prefer al dente), repeat from step 2,
  else drain it
--
https://mail.python.org/mailman/listinfo/python-list


Re: replacing `else` with `then` in `for` and `try`

2017-11-01 Thread Steve D'Aprano
On Thu, 2 Nov 2017 08:23 am, Ned Batchelder wrote:

> Apart from the questions of backward compatibility etc (Python is
> unlikely to ever go through another shift like the 2/3 breakage), are
> you sure "then" is what you mean?  This won't print "end":
> 
>  for i in range(10):
>  print(i)
>  else:
>  print(end)


You are neither the first nor the last person to have mistakenly understood
the "else" clause to run only if the main loop does not.

It is a common error. I've done it. And this demonstrates exactly why the
choice of keyword is so poor. If somebody of your experience can misread it,
I don't feel so bad about how long it too me to understand it when I was a
newbie.



-- 
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: replacing `else` with `then` in `for` and `try`

2017-11-01 Thread Steve D'Aprano
On Thu, 2 Nov 2017 08:21 am, Chris Angelico wrote:

> With the 'for' loop,
> it's a bit more arguable, but I've never seen anything more than a
> weak argument in favour of 'then'

Thhpptpt!

"else" is an completely inappropriate term that doesn't describe the semantics
of the statement even a little bit. The argument that it means "else no
break" is feeble because break is not the only way to exit the loop and
therefore skip executing the else clause.

It is not even necessarily the most common: I wouldn't be surprised if there
were more returns out of the middle of a loop than breaks, although I
wouldn't necessarily predict it either.

If we spoke in ordinary English using "else" the way Python uses it for
looping, we would say:

"Shampoo your hair twice, ELSE apply conditioner and leave for five minutes
before rinsing."

"Boil the pasta until it is soft, ELSE drain it and mix in the sauce."




-- 
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: replacing `else` with `then` in `for` and `try`

2017-11-01 Thread Steve D'Aprano
On Thu, 2 Nov 2017 08:12 am, Alexey Muranov wrote:

> Hello,
> 
> what do you think about the idea of replacing "`else`" with "`then`" in
> the contexts of `for` and `try`?


Yes, this, exactly!!!

(For while and for loops, but not try -- see below.)

I have argued this for many years. The current choice of "else" is painfully
misleading, and it causes people (including myself) to wrongly guess that
the "else" block runs only if the for/while block doesn't run at all:


# This is wrong!
for x in sequence:
...
else:
print("sequence is empty")


The actually semantics of "else" is that the block is UNCONDITIONALLY run
after the for/while loop completes, unless you jump out of the loop using
return, raise or break. That makes it a "then" block, not "else".


> It seems clear that it should be rather "then" than "else."  Compare
> also "try ... then ... finally" with "try ... else ... finally".

I disagree about the try block though. The semantics of the try block are:

try:
   A
except:
   B
else:
   C
finally:
   D

(1) code block A is attempted;

(2) IF an exception occurs, jump to code block B;

(3) otherwise (else), no exception occurs, so jump to code block C;

(4) finally run code block D on your way out, regardless of which blocks are
executed and how you exit them.


So I think "else" is correct here. The else block only gets called if there is
no exception.


> Currently, with "else", it is almost impossible to guess the meaning
> without looking into the documentation.

It is worse than that: it is easy to guess the WRONG meaning, namely that the
else block runs when the for/while loop doesn't execute at all (the for-loop
sequence is empty, or the while-loop condition is initially false).


> Off course, it should not be changed in Python 3, maybe in Python 4 or
> 5, but in Python 3 `then` could be an alias of `else` in these contexts.

Unfortunately, this is almost certainly not going to happen. It would require
adding a new keyword, and unless Guido changes his mind, he doesn't think
this change is worthwhile.

If I were the BDFL, this would be the first change I make :-)



-- 
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: replacing `else` with `then` in `for` and `try`

2017-11-01 Thread Ned Batchelder

On 11/1/17 5:29 PM, Chris Angelico wrote:

On Thu, Nov 2, 2017 at 8:23 AM, Ned Batchelder  wrote:

On 11/1/17 5:12 PM, Alexey Muranov wrote:

Hello,

what do you think about the idea of replacing "`else`" with "`then`" in
the contexts of `for` and `try`?

It seems clear that it should be rather "then" than "else." Compare also
"try ... then ... finally" with "try ... else ... finally".

Currently, with "else", it is almost impossible to guess the meaning
without looking into the documentation.

Off course, it should not be changed in Python 3, maybe in Python 4 or 5,
but in Python 3 `then` could be an alias of `else` in these contexts.

Alexey.


Apart from the questions of backward compatibility etc (Python is unlikely
to ever go through another shift like the 2/3 breakage), are you sure "then"
is what you mean?  This won't print "end":

 for i in range(10):
 print(i)
 else:
 print(end)

Well, it'll bomb with NameError when it tries to look up the *name*
end. But it will run that line of code - if you quote it, it will
work.

ChrisA


Naturally, I messed up on both a shallow and deep level! :) Or should I 
say derp level... :)


--Ned.
--
https://mail.python.org/mailman/listinfo/python-list


Re: replacing `else` with `then` in `for` and `try`

2017-11-01 Thread Chris Angelico
On Thu, Nov 2, 2017 at 8:23 AM, Ned Batchelder  wrote:
> On 11/1/17 5:12 PM, Alexey Muranov wrote:
>>
>> Hello,
>>
>> what do you think about the idea of replacing "`else`" with "`then`" in
>> the contexts of `for` and `try`?
>>
>> It seems clear that it should be rather "then" than "else." Compare also
>> "try ... then ... finally" with "try ... else ... finally".
>>
>> Currently, with "else", it is almost impossible to guess the meaning
>> without looking into the documentation.
>>
>> Off course, it should not be changed in Python 3, maybe in Python 4 or 5,
>> but in Python 3 `then` could be an alias of `else` in these contexts.
>>
>> Alexey.
>>
>
> Apart from the questions of backward compatibility etc (Python is unlikely
> to ever go through another shift like the 2/3 breakage), are you sure "then"
> is what you mean?  This won't print "end":
>
> for i in range(10):
> print(i)
> else:
> print(end)

Well, it'll bomb with NameError when it tries to look up the *name*
end. But it will run that line of code - if you quote it, it will
work.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: replacing `else` with `then` in `for` and `try`

2017-11-01 Thread Ned Batchelder

On 11/1/17 5:12 PM, Alexey Muranov wrote:

Hello,

what do you think about the idea of replacing "`else`" with "`then`" 
in the contexts of `for` and `try`?


It seems clear that it should be rather "then" than "else." Compare 
also "try ... then ... finally" with "try ... else ... finally".


Currently, with "else", it is almost impossible to guess the meaning 
without looking into the documentation.


Off course, it should not be changed in Python 3, maybe in Python 4 or 
5, but in Python 3 `then` could be an alias of `else` in these contexts.


Alexey.



Apart from the questions of backward compatibility etc (Python is 
unlikely to ever go through another shift like the 2/3 breakage), are 
you sure "then" is what you mean?  This won't print "end":


    for i in range(10):
    print(i)
    else:
    print(end)

--Ned.
--
https://mail.python.org/mailman/listinfo/python-list


Re: replacing `else` with `then` in `for` and `try`

2017-11-01 Thread Chris Angelico
On Thu, Nov 2, 2017 at 8:12 AM, Alexey Muranov  wrote:
> Hello,
>
> what do you think about the idea of replacing "`else`" with "`then`" in the
> contexts of `for` and `try`?
>
> It seems clear that it should be rather "then" than "else."  Compare also
> "try ... then ... finally" with "try ... else ... finally".
>
> Currently, with "else", it is almost impossible to guess the meaning without
> looking into the documentation.
>
> Off course, it should not be changed in Python 3, maybe in Python 4 or 5,
> but in Python 3 `then` could be an alias of `else` in these contexts.
>

The cost of creating a new keyword is incredibly high. You'll need to
demonstrate much more than a marginal improvement.

With try/except/else, it's "do this, and if an exception happens, do
this, else do this". So else makes perfect sense. With the 'for' loop,
it's a bit more arguable, but I've never seen anything more than a
weak argument in favour of 'then', and since it'd be a completely new
keyword, there's very approximately 0% chance that this will be
changed.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


replacing `else` with `then` in `for` and `try`

2017-11-01 Thread Alexey Muranov

Hello,

what do you think about the idea of replacing "`else`" with "`then`" in 
the contexts of `for` and `try`?


It seems clear that it should be rather "then" than "else."  Compare 
also "try ... then ... finally" with "try ... else ... finally".


Currently, with "else", it is almost impossible to guess the meaning 
without looking into the documentation.


Off course, it should not be changed in Python 3, maybe in Python 4 or 
5, but in Python 3 `then` could be an alias of `else` in these contexts.


Alexey.

--
https://mail.python.org/mailman/listinfo/python-list