On Sat, 9 Jan 2021, 8:50 pm Paul Sokolovsky, <pmiscml@gmail.com> wrote:
>
> The key difference relative to PEP 634 is that even when the code
> author uses the shorthand form, *readers* will still get at least the
> "as" keyword as a prompt,

Ok, so let's summarize the alternatives:

1. PEP634, which says that "case Cls(a, b):", etc. is not worse than
other languages.
2. PEP642, which says that taking existing "as" and using it (and it's
   also an English word with a specific meaning) with rather different
   meaning in pattern matching is ok.

I don't follow this objection. It's being used the same way it is used elsewhere in Python: binding a name given on the right based on information given on the left.

The shorthand to omit "__" is the only novelty that doesn't strictly follow that precedent.


3. Alternative proposal sounded on the list, which says that taking
   existing punctuational operator like ">" or "->" (and they're also
   graphemes depicturing arrows) and using them (still with rather
   different meaning) in pattern matching is ok.

PEP642 never mentions 3rd alternative.

Because PEP 634 doesn't propose it either.

And it actually starts its
presentation with things like:

> case {"host" as host, "port" as port}:

There're 2 obvious problems with it:

a) In Python, {} with things inside it, but no ":" inside it, is a set,
set.
b) Everywhere else in Python, thing on the left of "as" gets into
thing on the right of "as", behold:

import foo as bar  # original module "foo" gets into "bar".
with Cls(a, b) as c:  # original expression "Cls(a, b)" gets into "c"

Then based on the existing Python syntax, the meaning of '{"host" as
host, "port" as port}' is: a set, whose contained, constant in this
case, values "host" and "port" get captured as variables host and port.
In pattern matching context (with 'case' in front), it means: match
using a set, check for presence on constant "host" and "port" elements,
and capture those constants to variables host and port (that
capturing doesn't make much sense, yeah. And yet syntax tells just
that. You propose to assign to it completely different meaning.).

Yep, this is why I'd be entirely OK with the SC saying they'd prefer the colon to be mandatory, even when parsing is unambiguous without it.

I personally like the idea of being able to leave it out as redundant, but I definitely agree that the omission has the potential to make mapping patterns harder to interpret for readers.


So, the "dict pattern shortcut syntax" proposed by PEP642 is rather
ambiguous and confusing, and represent climax of PEP642's "fixing too
many things at once", where it goes over the summit and onto the dark
side.

And even looking at:

case {"host": as host, "port": as port}

I'm personally tripped by the meaning of "as" in English, and think
that it does something about thing on the left of it, i.e. the
dictionary *key*, not the *value*, as it really does.

It is as closely related to the key as the binding in with statements is to the context manager expression (in mapping patterns, it would bind the result of looking up the key, in with statements it binds the result of the __enter__ method).



> rather than having to just know that "name"
> appearing in a pattern means "__ as name",

But PEP634 doesn't have no "__ as name"! It has "_ as name". And
that's another case of PEP642's "too much at once". While that change
is pretty clearly presented in the PEP642, I find that discussion here
rather downplays it. Specifically, you use "__" even in the context
talking about PEP634, as if you take it for granted. Instead, each time
you mention "__", you'd rather say "which is another alternative syntax
PEP642 propose".

Because you see, I'm almost sure that readers of just this thread don't
even pay enough attention that you use double-underscore instead of the
original underscore. That leads us to the obvious concern:

1. The difference between "__" and "_" isn't visible enough.

People should start saying "OMG" and "horror!" now, not when PEP642 gets
implemented and they finally notice that they need to type _ twice.

Which leads us to:

2. Both PEP642 and discussion here should elaborate explicitly what
happens when people still use "_" in patterns.

It's a syntax error, because PEP 642 patterns don't allow the use of bare names.

So, you see, it says "many people prefer __", and then immediately says
"linters recognize _ as a special case". So, 10 years later, how many
linters recognize double-underscore as a special case too?

pylint does. I haven't checked the others, as pylint is the one I typically use.


Other general comments on PEP642v3 text:

> * allow an initial form of pattern matching to be developed and
> released without needing to decide up front on the best default
> options for handling bare names, attribute lookups, and literal values

Can this be made more explicit with appending: " (that's why it
proposes to prefix both capture patterns and value constraints, even
though prefixing just one would be enough to avoid ambiguity)".

I'd use "parsing ambiguity" at the end, but I agree that would be a useful clarification.


> MatchValue(matchop op, expr value)
> matchop = EqCheck | IdCheck

Why bloat ASDL with duplicates? Why not "matchop = Eq | Is" ?

Because that would result in a name conflict in the generated C code.



People should just learn pattern matching as it's presented in other
languages indeed. To help them with "may bind to the right" matter, a
very simple, focused change was proposed - to add explicit arrow
pointing straight at the bind/capture target.

I never liked that proposal, and it has absolutely zero to do with the origins of PEP 642 (remember, the PEP started out *not* qualifying name bindings, the same as PEP 634).

If you'd like to present specifically that proposal to the SC, then you're going to have to prepare your own PEP.

Instead of that simple
measure, PEP642 builds whole parallel hierarchy of concepts, which is
very artificial and complex response ("seeing complication,
rehash everything, and add significantly more overall complexity to deal
with originally simple case").   


Again, I pray for PEP642 rejection, based on its "attempting to do too
much, and overdoing it to "remedy is worse than the problem" situation,
and trying to build complex hierarchies to artificially separate
concepts in pattern matching, instead of treating pattern matching as
"cartesian product" of simple concepts (and see how to make these
simple concepts more explicit to humans, rather than adding more
constraints for humans to be aware of).

Deep and unobvious constraints, how on earth I know if some class
defines __match_args__ or not, so I can select appropriate syntax?

Instance attribute matching would work on any class. It's only positional matching that classes would have to opt in to by telling the interpreter what it means for instances of that class.

As for how you know whether a class supports custom matching, you'd find out the same way you find out if it can be called or used as a context manager: documentation, examples, and runtime introspection tools (e.g. class help in IDEs)

(Note: PEP 634 has the same distinction, where only classes that define __match_args__ can accept positional patterns in cases)


I
simply will use the syntax which is usable for all cases (and that's the
ugly one), and the other syntax will be used only for builtin types,
and whoever will see it used for a non-builtin class will be shocked and
confused.

Why would they be any more shocked and confused by that than they would by classes defining custom constructors that take positional arguments, or implementing the context management protocol?

Cheers,
Nick.



[]

--
Best regards,
 Paul                          mailto:pmiscml@gmail.com