Hello,

On Sun, 10 Jan 2021 01:42:25 +1000
Nick Coghlan <ncogh...@gmail.com> wrote:

> On Sat, 9 Jan 2021, 8:50 pm Paul Sokolovsky, <pmis...@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.

Where's "left" in the case of your proposed syntax:

case [as a, as b]:

?

There's no "left". And that's the whole point, in your PEP642
proposal, "as" applies to implicitly given term, encoded by position in
the match pattern. That's ... unusual. And ... confusing, at least at
first. As I said, maybe we could get used to it, but I always bring
that matter in comparison to the alternative syntax, which IMHO avoids
confusion implied by both English and current Python meaning of "as": 

case [>a, >b]:

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

Well, PEP622 did have it:
https://www.python.org/dev/peps/pep-0622/#alternatives-for-constant-value-pattern
 ,
quoting (last bullet point there):

>>> There was also an idea to make lookup semantics the default, and
>>> require $ or ? to be used in capture patterns:

Then we know the issues with PEP622/PEP634, that requests/proposals for
various clarifications to them were denied. That's how PEP642 was born,
according to its own text. The more strange that it continues that
cycle of hushing/avoiding mentioning alternative ideas. 

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

That's great, thanks for considering it!

But in the formal review process what we have is:

1) It's v3 of PEP642, which still has such an issue.
2) Its author doesn't admit that there's objective ambiguity between
mapping pattern syntax in PEP642 and would-be set patterns, and treat
that issue as subjective, saying that he'd make a change if SC asks for
it, not because he has seen the issue with it, based on the community
feedback.

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

Sorry, we talk about surface syntax here, not underlying semantics. And
syntax of:

{"host" as host}

isn't consistent with

with open("foo") as f:

If you wanted to expose deeper semantics with the first syntax, you
would probably come up with something like {["host"] as host} - that's
truly "expliticize" the fact "it would bind the result of looking the
key", ain't it?

But all that is just going deeper down the rabbit whole. Because the
right syntax *and* meaning, consistent with sequence patterns is:

{"host": as host}

where "as host" stands in for the *value* in dict entry corresponding to
a key, and the fact which you bring up - that it would be looked up by
that key - is irrelevant implementation detail, as far as *syntax* is
concerned.


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

Good. Please consider adding explicit paragraph describing that (in
detail whenever possible, hence paragraph.) That would be important
argument for the people wary of confusion "__" may bring. 

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

I'd recommend to add that info to the PEP. Again, it strengthens the
cause, showing that it has some prior art, not just adhoc "original
design" made up on spot.

[]

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

I have my conceptual model of origins of PEP642: there were calls on
the list from various people to consider "sigil" alternatives to
PEP634: a) to add sigils for value patterns; alternatively b) to add
sigils to capture patterns. You picked the idea "a)", which was great
rejoice. Sadly, nobody paid enough attention to the idea b), though the
whole [my] idea was to contrast the *two*.

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

I don't think I'm qualified to write a PEP. How I treat it is that if
I'm the only one who finds it an interesting choice, it's already lost.
You ended up going the same "sigil for capture patterns" way, except you
chose word "as" as a sigil, instead of punctuation like ">" or "->". In
that regard, it would be instructive if your PEP elaborated why "you
never liked punctuation proposal", how is it much different from "word
as sigil" up to you *never* liking it.

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

That's what I was saying, yes.

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

The matter, most of us don't write *new* context managers that often. I
do write them, but mostly as wrappers for existing context managers. I
don't remember signature for __exit__. How I write it is:

    def __exit__(self, *args):
        return self.wrapper.__exit__(*args)

That all is supposed to be different for matter matching, as it's
supposed to be used with multitude of classes we have to represent
data objects. And most people won't bother to lookup/remember
__match_args__, they will [have to] use obj{.attr} syntax. But they will
see Cls(attr) syntax in other people's code and in regard to objects
coming from 3rd-party libs, and will be in permanent state of confusion
regarding what chasm lies between their own classes and those libs'.

If you says that will cause them to learn the difference, then yes, on
a free day of Xmas holidays they will look it up, tweet their amazement
that someone did such a thing to the language, and then safely forgot
about it, just swearing about foo{.bar} vs foo(bar) pattern matching
dichotomy once in a while.

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

But classes which don't define it, still use the same syntax, just with
"keywords for attributes instead of positional args", instead of
completely unheard syntax of obj{.attr1, .attr2} which you propose!


And all that because you insist that:

host, port = addr{.host, .port}

is anyhow better than:

Addr(host = >host, port = >port) = addr


> 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:pmis...@gmail.com
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/7F4ZNGT4AFS5BGNEUVNXHGQQAZY7CC7M/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to