On Fri., 31 Jul. 2020, 3:14 am Guido van Rossum, <guido@python.org> wrote:
On Wed, Jul 29, 2020 at 4:34 PM Nick Coghlan <ncoghlan@gmail.com> wrote:
I'm still only intermittently keeping up on python-dev, but my main concern with the first iteration remains in this version, which is that it doesn't even *mention* that the proposed name binding syntax inherently conflicts with the existing assignment statement lvalue syntax in two areas:

I don't see why the PEP would be required to mention this. You make it sound like it's a bad thing (a "conflict"), whereas the PEP authors' position is that it is irrelevant.
 
* dotted names (binds an attribute in assignment, looks up a constraint value in a match case)
* underscore targets (binds in assignment, wildcard match without binding in a match case)

The latter could potentially be made internally consistent in the future by redefining "_" and "__" as soft keywords that don't get bound via normal assignment statements either (requiring that they be set via namespace dict modification instead for use cases like il8n). https://www.python.org/dev/peps/pep-0622/#use-some-other-token-as-wildcard presents a reasonable rationale for the usage, so it's only flaw is failing to mention the inconsistency.

That solution is outside the scope of the PEP -- it would be a big backward incompatibility with little payoff. Your repeated mention of consistency makes me want to quote PEP 8 (quoting Emerson, though I didn't even know who that was when I put it in my style guide :-): "A foolish consistency is the hobgoblin of little minds."

I don't really like that future possibility either - I think it would be much better for PEP 622 to let "_" be a binding throwaway variable as normal, and allow a bare "?" as the "match any expression without binding it" marker.

But unlike the reuse of attribute assignment syntax for a different purpose, it's a conflict that I don't think matters very much (as it's incredibly rare to care whether binding "_" actually creates a reference or not, so having it bind sometimes and not others isn't likely to present any major barriers to learning).

The former syntactic conflict presents a bigger problem, though, as it means that we'd be irrevocably committed to having two different lvalue syntaxes for the rest of Python's future as a language.

Things become much less "conflict-y" if you stop seeing patterns as lvalues. They just aren't, and any argument based on the idea that they are is inherently flawed.

That's conceding my point, though: aside from iterable unpacking, the PEP isn't currently even trying to keep pattern matching syntax consistent with assignment target syntax, as the PEP authors haven't even considered the idea of pursuing a higher level of consistency as a design goal.

A section titled "Match patterns are not assignment targets" that explains that even though match patterns bind names and do iterable unpacking the same way assignment targets do, it is nevertheless incorrect for a reader to think of them as assignment targets would address my concern (it wouldn't convince me that it is a good idea to view the design problem that way, but I would accept that the argument had been heard and addressed in a context where the future PEP delegate will necessarily see it).

(Also note that the concept of lvalue isn't even defined in Python. There are a variety of assignment targets with different syntactic constraints depending on context, and several other syntactic constructs that bind names.)

Right, I just use "lvalue" as a shorthand for "syntax that can bind a name". All the others are strict subsets of the full assignment target syntax, though, mostly falling into either "simple names only" or "simple names and iterable unpacking, but no attributes or subscripts". I'll use "name binding context" for the full set of those below.

This PEP is the first time it has been proposed to accept valid assignment target syntax in a name binding context, but have it mean something different.
The fact that the PEP doesn't even acknowledge that this is a potential problem is the biggest part of the problem. If the problem was acknowledged, and addressed, then readers could evaluate the merits of PEP authors' arguments against it.

As it is, unless the reader identifies the conflict on their own, they may not realise what is bugging them about it, and make the same mistake I initially did and believe it's the binding syntax that's inconsistent (when that's actually entirely consistent with for loops, for example), rather than the constraint lookup syntax (which has never previously been allowed in a name binding context).

We know the PEP authors don't see patterns as assignment targets beyond sharing the iterable unpacking syntax, but my concern is for everyone *else* that is either learning pattern matching as an existing Python developer, or learning Python in general after match statements are added, and is trying to figure out why these two snippets do the same thing:

    x = y

    match y:
        case x:
            pass

and so do these:

   a, b = x, y

    match (x, y):
        case a, b:
            pass

while the second snippet here throws NameError if the attribute doesn't exist yet, or silently does nothing if it does:

    x.a = y

    match y:
        case x.a:
            pass

If that consistently threw SyntaxError instead (which is what I am suggesting it should do in the absence of a leading "?" on the constraint expression), then it would be similar to the many other places where we allow binding simple names and iterable unpacking, but not attributes or subscripts.

As it is, it's the tipping point where learners will be forced to realise that there is a semantic inconsistency between pattern matching syntax and assignment target syntax.

If the PEP authors are deliberately championing that inconsistency, then it will be up to the PEP delegate to decide if it is a deal breaker or not. But right now, the PEP isn't even acknowledging that this is a significant design decision that the PEP authors have made.

Cheers,
Nick.