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

Chris Angelico rosuav at gmail.com
Tue Nov 7 14:10:08 EST 2017


On Wed, Nov 8, 2017 at 4:28 AM, Ian Kelly <ian.g.kelly at gmail.com> wrote:
> On Sat, Nov 4, 2017 at 6:40 AM, Chris Angelico <rosuav at gmail.com> wrote:
>> On Sat, Nov 4, 2017 at 11:25 PM, Jon Ribbens <jon+usenet at unequivocal.eu> wrote:
>>> On 2017-11-04, Ben Finney <ben+python at benfinney.id.au> 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 "<stdin>", 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 "<stdin>", 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 could trap something if it's a known bug magnet,
but it has to be a pretty serious bug magnet to justify that.

ChrisA



More information about the Python-list mailing list