Mailing List Archive

1 2 3 4 5 6 7  View All
Re: PEP 622 version 2 (Structural Pattern Matching) [ In reply to ]
On 16/07/2020 19:00, Rhodri James wrote:
> On 16/07/2020 17:37, Steve Holden wrote:
>> While I understand the point of view that says that match ... :
>> should encapsulate a sequence of indented suites, it seems to me that
>> match/case/case/.../else has a natural affinity with
>> try/except/except/.../finally/else, and nobody seems to think that the
>> excepts should be indented. Or the finally. And naturally the match/else
>> case are at the same indentation level, just as for/else, while/else and
>> try/finally. So why, exactly, should case be indented?
> [...]
> If we did:
>
>     match:
>         <expression>
>     case <pattern>:
>         <suite>
>
> then having an indented section which must be a single expression
> would be unique in Python syntax.
>
> [...]
>
> match <expression>:
>     case <pattern>:
>         <suite>
>
> would be the one place in Python where you end a line with a colon and
> **don't** indent the following line.

It seems relevant to mention that before Python's unique syntax for a
ternary operator (x = something if something else default_value), you
would never find an if or else without a colon and an indented block,
and the order (value, condition, default) is different than what is
usually found in other languages (condition, value, default). That
hasn't stopped Python from implementing the feature in its own way and I
don't see why this PEP should be different, since Python is not other
languages and match suites are not other suites.

> I could easily see people being confused when the slew of statements
> they would inevitably decide they must be able to put there, and soon
> we'd have cats and dogs living together and the downfall of
> civilisation as we know it.
> [...]
> Writers of simple formatters and the like (such as Python-mode in
> Emacs) would curse your name, etc, etc.
Tools should adapt to the language, not the other way around. If things
had to be done the way they had always been done, without any change,
for fear of people not being used to it, we wouldn't even have Python at
all. People learn and adapt. It seems like a small price to pay in
exchange for consistency and removal of ambiguity, considering people
will still have to learn the new feature one way or another.
Re: PEP 622 version 2 (Structural Pattern Matching) [ In reply to ]
On Fri, Jul 17, 2020 at 3:25 AM Federico Salerno <salernof11@gmail.com> wrote:
> Tools should adapt to the language, not the other way around. If things had to be done the way they had always been done, without any change, for fear of people not being used to it, we wouldn't even have Python at all. People learn and adapt. It seems like a small price to pay in exchange for consistency and removal of ambiguity, considering people will still have to learn the new feature one way or another.
>

But consistency is exactly what you'd be destroying here. Python is
extremely consistent in that you ALWAYS indent after a line ends with
a colon, and what comes after it is logically contained within that
statement. It's about whether *people* can handle it, more than
whether tools can, and the consistency helps a lot with that.

ChrisA
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-leave@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/S56BYBQIWTV2SQYBTYT3ZRPNI7CLF5MR/
Code of Conduct: http://python.org/psf/codeofconduct/
Re: PEP 622 version 2 (Structural Pattern Matching) [ In reply to ]
> On Jul 16, 2020, at 1:36 PM, Chris Angelico <rosuav@gmail.com> wrote:
>
> ?On Fri, Jul 17, 2020 at 3:25 AM Federico Salerno <salernof11@gmail.com> wrote:
>> Tools should adapt to the language, not the other way around. If things had to be done the way they had always been done, without any change, for fear of people not being used to it, we wouldn't even have Python at all. People learn and adapt. It seems like a small price to pay in exchange for consistency and removal of ambiguity, considering people will still have to learn the new feature one way or another.
>>
>
> But consistency is exactly what you'd be destroying here. Python is
> extremely consistent in that you ALWAYS indent after a line ends with
> a colon, and what comes after it is logically contained within that
> statement. It's about whether *people* can handle it, more than
> whether tools can, and the consistency helps a lot with that.
>
> ChrisA
>
One question that comes to mind, does match NEED a colon at the end of it? If it didn’t have the colon, it wouldn’t need the indent for the following lines.
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-leave@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/M7CVHHBR5IGIUCFH4Y7S6I7FQWXTEE64/
Code of Conduct: http://python.org/psf/codeofconduct/
Re: PEP 622 version 2 (Structural Pattern Matching) [ In reply to ]
On 2020-07-16 19:05, Richard Damon wrote:
>> On Jul 16, 2020, at 1:36 PM, Chris Angelico <rosuav@gmail.com> wrote:
>>
>> ?On Fri, Jul 17, 2020 at 3:25 AM Federico Salerno <salernof11@gmail.com> wrote:
>>> Tools should adapt to the language, not the other way around. If things had to be done the way they had always been done, without any change, for fear of people not being used to it, we wouldn't even have Python at all. People learn and adapt. It seems like a small price to pay in exchange for consistency and removal of ambiguity, considering people will still have to learn the new feature one way or another.
>>>
>>
>> But consistency is exactly what you'd be destroying here. Python is
>> extremely consistent in that you ALWAYS indent after a line ends with
>> a colon, and what comes after it is logically contained within that
>> statement. It's about whether *people* can handle it, more than
>> whether tools can, and the consistency helps a lot with that.
>>
>> ChrisA
>>
> One question that comes to mind, does match NEED a colon at the end of it? If it didn’t have the colon, it wouldn’t need the indent for the following lines.
>
All of the others have the colon.
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-leave@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/Z63GPE46RPULXJRIFVOBF4DDM3BCKD5B/
Code of Conduct: http://python.org/psf/codeofconduct/
Re: PEP 622 version 2 (Structural Pattern Matching) [ In reply to ]
On 7/16/2020 10:00 AM, Rhodri James wrote:
> On 16/07/2020 17:37, Steve Holden wrote:
>> While I understand the point of view that says that match ... :
>> should encapsulate a sequence of indented suites, it seems to me that
>> match/case/case/.../else has a natural affinity with
>> try/except/except/.../finally/else, and nobody seems to think that the
>> excepts should be indented. Or the finally. And naturally the match/else
>> case are at the same indentation level, just as for/else, while/else and
>> try/finally. So why, exactly, should case be indented?
>
> My take on the difference would be that "try" tries out a suite, while
> "match" matches an expression.  If we did:
>
>     match:
>         <expression>
>     case <pattern>:
>         <suite>
>
> then having an indented section which must be a single expression
> would be unique in Python syntax.  I could easily see people being
> confused when the slew of statements they would inevitably decide they
> must be able to put there, and soon we'd have cats and dogs living
> together and the downfall of civilisation as we know it.
>
> Alternatively:
>
>     match <expression>:
>     case <pattern>:
>         <suite>
>
> would be the one place in Python where you end a line with a colon and
> *don't* indent the following line.  Writers of simple formatters and
> the like (such as Python-mode in Emacs) would curse your name, etc, etc.
>
>> My apologies for being a Bear of Very Little Brain.
>
> Nah, don't apologise.  This is one of those things that everyone has
> opinions on, because there doesn't seem to be an obvious Right Answer.
>

Speaking of things unique in Python syntax, isn't double-indention of a
single control flow structure introduced by match also unique?
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-leave@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/E26GHBGQCGROPUJZBRY66GVKDWOQT4ZX/
Code of Conduct: http://python.org/psf/codeofconduct/
Re: PEP 622 version 2 (Structural Pattern Matching) [ In reply to ]
On 16/07/2020 18:13, MRAB wrote:
> On 2020-07-16 17:37, Steve Holden wrote:
>> While I understand the point of view that says that match ... :
>> should encapsulate a sequence of indented suites, it seems to me that
>> match/case/case/.../else has a natural affinity with
>> try/except/except/.../finally/else, and nobody seems to think that
>> the excepts should be indented. Or the finally. And naturally the
>> match/else case are at the same indentation level, just as for/else,
>> while/else and try/finally. So why, exactly, should case be indented?
>>
>> My apologies for being a Bear of Very Little Brain.
>>
> [snip]
> For all other statement structures (if, while, try, etc.), the first
> line ends with a colon and the second line is indented (and is a
> statement). Therefore the cases should be indented.
>
> However, for all other statement structures (if, while, try, etc.),
> the other parts of the structure itself (elif, else, except, etc.)
> aren't indented. Therefore the cases shouldn't be indented.
>
> Either way, it's inelegant.
Absolutely true.  However:

I think that equal indentation suggests suites of equal status.
Increased indentation suggests suites are subordinate to a previous suite.
Consider these examples:

(1) if..elif...else: Suites are definitely co-equal (they are
alternatives, only one of which is chosen).  So if/elif/else have equal
indentation.
(2) for...else or while...else: It's arguable IMO (YMMV); Python has
chosen to indent them equally.  I don't think it would have been
outrageous to indent the 'else:';  one reason not to is that the 'else'
might not stand out (it would typically be indented equally with the
preceding line of code), unless it was allowed/forced to be indented
*less than* 'for'.
(3) try...except...else:  IMO also arguable (at most one of 'except' and
'else' can be executed).
(4) try...finally: The suites have equal status (both are always
executed), so they have equal indentation.

Now to me, 'case' clauses are *subordinate* to 'match'.  After all, the
value after 'match' applies to all the following 'case's.  So I would
argue in favour of indenting 'case' statements.  This would make them
stand out *more* (making a virtue out of 'match' *not* being followed by
an indented suite).  A Good Thing.  One of the purposes of indentation
is to make program structure clearly visible, which IMO this would do.

Or from a slightly different point of view: "match...case...case..." is
a single construct, a self-contained program component. Indenting the
'case's would stop them from distracting visually from other suites that
are indented the same as 'match'.  (I.e. other program components of
equal status.)

(If 'else' were allowed after 'match', I would argue that it should also
be indented, for the same reasons, and because it is logically a case,
albeit a special one.)

Rob Cliffe
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-leave@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/3OAUJHV4THFUSBUPLVLULVWM4SADAW2B/
Code of Conduct: http://python.org/psf/codeofconduct/
Re: PEP 622 version 2 (Structural Pattern Matching) [ In reply to ]
Hello everyone,

I'm sorry if my proposition has already being said, or even withdrawn,
but I think that capture variables shouldn't be as implicit as they
are now. I didn't see any mention of capture variable patterns in
the rejected ideas. So here is my idea:

I've looked at the PEP very quickly, jumping on the examples to have
a taste and an idea of what was going here. I saw a new kind of control
structure based on structural pattern matching (pattern based on
classes or compositions of classes to make it short). A very good
idea, emphasized by Tobias Kohn ("Another take on PEP 622") is that
pattern matching eases the writting of code based on matching such
structures, and that capturing values stored inside of these
structures at the match time really eases the writting of the code
associated with this match.

But... looking at the examples, it wasn't very obvious that some
variables were catching variables and some others were matching ones.
I then read in details some rules about how to discover what is a
captured variable. But I'm not sure everybody will do this...

Zen of Python tells us that "explicit is better than implicit". I know
this is not a rule written in the stone, but I think here, it applies
very well.

Guido said :
> We’re really looking
> for a solution that tells you when you’re looking at an individual
> case which variables are captured and which are used for
> load-and-compare.
>
> Marking up the capture variables with some sigil (e.g. $x or
> x?)
> or other markup (e.g. backticks or <x>) makes this common case ugly
> and inconsistent: it’s unpleasant to see for example
>
> case %x, %y:
> print(x, y)

Guido talk about a "sigil", which seems to be a meaningless mark only
here to help the parser understand what the dev was writing.

I propose that this "sigil" be the affectation mark : "=". Look :

z = 42
match pt:
case x=, y=, z:
print(x, y, "z == 42")

Or this one :

def make_point_3d(pt):
match pt:
case (x=, y=):
return Point3d(x, y, 0)
case (x=, y=, z=):
return Point3d(x, y, z)
case Point2d(x=, y=):
return Point3d(x, y, 0)
case Point3d(_, _, _):
return pt
case _:
raise TypeError("not a point we support")

On the need to be explicit:

Simple case blocks will perhaps be a bit longer to write, but will
not be harder to read, since they stay in the "simple case blocks"
family.

More complex cases will be harder to write, but the explicit markup
will help understand what will be captured and where, and what will
be looked-and-matched, using already known rules : looked-and-matched
expressions will be computed as usual, then compared with the match
term, and captured expression will be computed to a l-value (which
is much more restrictive than random expressions).

Moreover, explicilty introducing a difference between "capture" and
"look-and-match" will help newcomers to understand what is the point
about a match without they have to look at a PEP or other normative
document.

Remember that code has to be readable, because it will be read much
more often than written. The reader has to understand quickly but not
in details what will happen. Being explicit removes they the task
to concentrate on this point.

Also remember that Python has to be teached, and that all that is
implicit in the code have to be explicited when teaching. And the
longer you teach microdetails like what is the difference between
"capture" vs "look-and-match", the less your audience will be prone
to listen to you.

On the drawback to be explicit:

Adding a mark to every captured variables can and will be annoying.
More annoying than not adding it. It's obvious. But we don't expect to
have more than a handful of captured variables per case. Or the case
is perhaps too complex, not to say perhaps too complicated.

Using a carrefully choosen mark can alleviate this drawback. Using
an already accepted and commonly used symbol will surely help.

I know that Python will diverge from other languages on this point. Yes,
but Python already diverged from others languages, and it is see
by the community that it is for the better. Ex : the conditional expression
aka the "ternary operator" aka "x = blabla if plop else bla".

And I'll be a bit confused to have to explain that "captured variables"
look like simple expressions "but are not" because that's how things
are written in other functionnal languages. I'm not sure it will
convince anybody that aren't already familiar with pattern matching in
functionnal languages (which is a big topic by itself).

On the syntax:

Using the "=" character is well know, easy to find on a keyboard
and already hold the semantics of "putting a value in a variable".

So this mark is not a random sigil, but the way we write
affectations, with a l-value, a "=" character, and a
r-value. The r-value is given from the match and is omited here.

And even if only a few ones know what "l-value" means, everybody knows
what is allowed to put on the left side of an "=".

Morever, this kind of syntax already exists in the Python world, when
using default function parameters values :

def make_point(x=0, y=0):
return x, y

Here the r-value is present. The l-value still has a defined
semantic that is easy to learn and understand without requiring
to read the Python semantics book or any PEPs. And this is still
the same semantic of "putting a value in a variable".

And see how there is "x=" in the definition, but just "x" in the body
of the function. Like in the case block.

That's why I think it will add value to be explicit about captured
variable, and that choosing a meaningfull mark can clarify many
implicit, and hard to understand, patterns.

Emmanuel
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-leave@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/RDEKWUZ657BE5KSYVF7IF2N47XRQ5DEV/
Code of Conduct: http://python.org/psf/codeofconduct/
Re: PEP 622 version 2 (Structural Pattern Matching) [ In reply to ]
On Fri, 17 Jul 2020 at 12:26, <emmanuel.coirier@caissedesdepots.fr> wrote:

> Hello everyone,
>
> I'm sorry if my proposition has already being said, or even withdrawn,
> but I think that capture variables shouldn't be as implicit as they
> are now. I didn't see any mention of capture variable patterns in
> the rejected ideas. So here is my idea:
>
> I've looked at the PEP very quickly, jumping on the examples to have
> a taste and an idea of what was going here. I saw a new kind of control
> structure based on structural pattern matching (pattern based on
> classes or compositions of classes to make it short). A very good
> idea, emphasized by Tobias Kohn ("Another take on PEP 622") is that
> pattern matching eases the writting of code based on matching such
> structures, and that capturing values stored inside of these
> structures at the match time really eases the writting of the code
> associated with this match.
>
> But... looking at the examples, it wasn't very obvious that some
> variables were catching variables and some others were matching ones.
> I then read in details some rules about how to discover what is a
> captured variable. But I'm not sure everybody will do this...
>
> Zen of Python tells us that "explicit is better than implicit". I know
> this is not a rule written in the stone, but I think here, it applies
> very well.
>
> Guido said :
> > We’re really looking
> > for a solution that tells you when you’re looking at an individual
> > case which variables are captured and which are used for
> > load-and-compare.
> >
> > Marking up the capture variables with some sigil (e.g. $x or
> > x?)
> > or other markup (e.g. backticks or <x>) makes this common case ugly
> > and inconsistent: it’s unpleasant to see for example
> >
> > case %x, %y:
> > print(x, y)
>
> Guido talk about a "sigil", which seems to be a meaningless mark only
> here to help the parser understand what the dev was writing.
>
> I propose that this "sigil" be the affectation mark : "=". Look :
>
> z = 42
> match pt:
> case x=, y=, z:
> print(x, y, "z == 42")
>
> Or this one :
>
> def make_point_3d(pt):
> match pt:
> case (x=, y=):
> return Point3d(x, y, 0)
> case (x=, y=, z=):
> return Point3d(x, y, z)
> case Point2d(x=, y=):
> return Point3d(x, y, 0)
> case Point3d(_, _, _):
> return pt
> case _:
> raise TypeError("not a point we support")
>
>
I kind of agree it is nicer to be more explicit. But somehow x= looks
ugly. It occurred to me (and, again, apologies if already been mentioned),
we might use the `as` keyword here.

The example above would become:

def make_point_3d(pt):
match pt:
case (as x, as y):
return Point3d(x, y, 0)
case (as x, as y, as z):
return Point3d(x, y, z)
case Point2d(as x, as y):
return Point3d(x, y, 0)
case Point3d(_, _, _):
return pt
case _:
raise TypeError("not a point we support")

If having "as x" as a standalone expression without anything to the left of
"as" causes confusion, we could instead mandate the use of _ thus:

case (_ as x, _ as y):
return Point3d(x, y, 0)

On the need to be explicit:
>
> Simple case blocks will perhaps be a bit longer to write, but will
> not be harder to read, since they stay in the "simple case blocks"
> family.
>
> More complex cases will be harder to write, but the explicit markup
> will help understand what will be captured and where, and what will
> be looked-and-matched, using already known rules : looked-and-matched
> expressions will be computed as usual, then compared with the match
> term, and captured expression will be computed to a l-value (which
> is much more restrictive than random expressions).
>
> Moreover, explicilty introducing a difference between "capture" and
> "look-and-match" will help newcomers to understand what is the point
> about a match without they have to look at a PEP or other normative
> document.
>
> Remember that code has to be readable, because it will be read much
> more often than written. The reader has to understand quickly but not
> in details what will happen. Being explicit removes they the task
> to concentrate on this point.
>
> Also remember that Python has to be teached, and that all that is
> implicit in the code have to be explicited when teaching. And the
> longer you teach microdetails like what is the difference between
> "capture" vs "look-and-match", the less your audience will be prone
> to listen to you.
>
> On the drawback to be explicit:
>
> Adding a mark to every captured variables can and will be annoying.
> More annoying than not adding it. It's obvious. But we don't expect to
> have more than a handful of captured variables per case. Or the case
> is perhaps too complex, not to say perhaps too complicated.
>
> Using a carrefully choosen mark can alleviate this drawback. Using
> an already accepted and commonly used symbol will surely help.
>
> I know that Python will diverge from other languages on this point. Yes,
> but Python already diverged from others languages, and it is see
> by the community that it is for the better. Ex : the conditional expression
> aka the "ternary operator" aka "x = blabla if plop else bla".
>
> And I'll be a bit confused to have to explain that "captured variables"
> look like simple expressions "but are not" because that's how things
> are written in other functionnal languages. I'm not sure it will
> convince anybody that aren't already familiar with pattern matching in
> functionnal languages (which is a big topic by itself).
>
> On the syntax:
>
> Using the "=" character is well know, easy to find on a keyboard
> and already hold the semantics of "putting a value in a variable".
>
> So this mark is not a random sigil, but the way we write
> affectations, with a l-value, a "=" character, and a
> r-value. The r-value is given from the match and is omited here.
>
> And even if only a few ones know what "l-value" means, everybody knows
> what is allowed to put on the left side of an "=".
>
> Morever, this kind of syntax already exists in the Python world, when
> using default function parameters values :
>
> def make_point(x=0, y=0):
> return x, y
>
> Here the r-value is present. The l-value still has a defined
> semantic that is easy to learn and understand without requiring
> to read the Python semantics book or any PEPs. And this is still
> the same semantic of "putting a value in a variable".
>
> And see how there is "x=" in the definition, but just "x" in the body
> of the function. Like in the case block.
>
> That's why I think it will add value to be explicit about captured
> variable, and that choosing a meaningfull mark can clarify many
> implicit, and hard to understand, patterns.
>
> Emmanuel
> _______________________________________________
> Python-Dev mailing list -- python-dev@python.org
> To unsubscribe send an email to python-dev-leave@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/RDEKWUZ657BE5KSYVF7IF2N47XRQ5DEV/
> Code of Conduct: http://python.org/psf/codeofconduct/
>


--
Gustavo J. A. M. Carneiro
Gambit Research
"The universe is always one step beyond logic." -- Frank Herbert
Re: PEP 622 version 2 (Structural Pattern Matching) [ In reply to ]
On 7/17/20 8:26 AM, Gustavo Carneiro wrote:

> I kind of agree it is nicer to be more explicit.  But somehow x= looks
> ugly. It occurred to me (and, again, apologies if already been
> mentioned), we might use the `as` keyword here.

The problem with any kind of sigil/keyword is that it becomes line noise
-- we would have to train ourselves to ignore them in order to see the
structure and variables we are actually interested in. Once we become
adept at ignoring them, we will again have difficulties when debugging
as we won't easily see them.

Besides which, the problem is solved:

- namespace.var is a lookup
- var is a store

--
~Ethan~
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-leave@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/TUQMGYFL4PDEP2VVTRNHDQHQLQ4ELZ4Y/
Code of Conduct: http://python.org/psf/codeofconduct/
Re: PEP 622 version 2 (Structural Pattern Matching) [ In reply to ]
I've built the reference implementation and I'm experimenting with the
new syntax in the edgedb codebase. It seems to have plenty of places
where pattern matching adds clarity. I'll see if I find particularly
interesting examples of that to share.

So far I'm +1 on the proposal, and I like the second iteration of it.
Except that I'm really sad to see the __match__ protocol gone.

Quoting the PEP:

> One drawback of this protocol is that the arguments to __match__ would be expensive to construct, and could not be pre-computed due to the fact that, because of the way names are bound, there are no real constants in Python.

While it's not possible to precompute the arguments ahead of time, it
certainly should be possible to cache them similarly to how I
implemented global names lookup cache in CPython. That should
alleviate this particular performance consideration entirely.

Having __match__ would allow some really interesting use cases. For
example, for binary protocol parsers it would be possible to replicate
erlang approach, e.g.:

match buffer:
case Frame(char('X'), len := UInt32(), flags := Bits(0, 1, flag1,
flag2, 1, 1))

would match a Frame of message type 'X', capture its length, and
extract two bit flags. This perhaps isn't the greatest example of how
a full matching protocol could be used, but it's something that I
personally wanted to implement.

Yury
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-leave@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/SCJ6H6KAE2WNHIVOEQ7M5YCZMU4HCYN6/
Code of Conduct: http://python.org/psf/codeofconduct/
Re: PEP 622 version 2 (Structural Pattern Matching) [ In reply to ]
On Fri, Jul 17, 2020 at 1:45 PM Yury Selivanov <yselivanov.ml@gmail.com>
wrote:

> I've built the reference implementation and I'm experimenting with the
> new syntax in the edgedb codebase. It seems to have plenty of places
> where pattern matching adds clarity. I'll see if I find particularly
> interesting examples of that to share.
>
> So far I'm +1 on the proposal, and I like the second iteration of it.
> Except that I'm really sad to see the __match__ protocol gone.
>

It will be back, just not in 3.10. We need more experience with how
match/case are actually used to design the right `__match__` protocol.


> Quoting the PEP:
>
> > One drawback of this protocol is that the arguments to __match__ would
> be expensive to construct, and could not be pre-computed due to the fact
> that, because of the way names are bound, there are no real constants in
> Python.
>

Note: That's not referring to the `__match__` protocol from version 1 of
the PEP, but to a hypothetical (and IMO sub-optimal) `__match__` protocol
that was discussed among the authors prior to settling on the protocol from
version 1.


> While it's not possible to precompute the arguments ahead of time, it
> certainly should be possible to cache them similarly to how I
> implemented global names lookup cache in CPython. That should
> alleviate this particular performance consideration entirely.
>

Where's that global names lookup cache? I seem to have missed its
introduction. (Unless you meant PEP 567?)


> Having __match__ would allow some really interesting use cases. For
> example, for binary protocol parsers it would be possible to replicate
> erlang approach, e.g.:
>
> match buffer:
> case Frame(char('X'), len := UInt32(), flags := Bits(0, 1, flag1,
> flag2, 1, 1))
>
> would match a Frame of message type 'X', capture its length, and
> extract two bit flags. This perhaps isn't the greatest example of how
> a full matching protocol could be used, but it's something that I
> personally wanted to implement.
>

I see, you'd want the *types* of the arguments to be passed into
`Frame.__match__`. That's interesting, although I have a feeling that if I
had a real use case like this I'd probably be able to come up with a better
DSL for specifying messages than this.

--
--Guido van Rossum (python.org/~guido)
*Pronouns: he/him **(why is my pronoun here?)*
<http://feministing.com/2015/02/03/how-using-they-as-a-singular-pronoun-can-change-the-world/>
Re: PEP 622 version 2 (Structural Pattern Matching) [ In reply to ]
On Fri, Jul 17, 2020 at 3:54 PM Guido van Rossum <guido@python.org> wrote:
>
> On Fri, Jul 17, 2020 at 1:45 PM Yury Selivanov <yselivanov.ml@gmail.com> wrote:
>>
>> I've built the reference implementation and I'm experimenting with the
>> new syntax in the edgedb codebase. It seems to have plenty of places
>> where pattern matching adds clarity. I'll see if I find particularly
>> interesting examples of that to share.
>>
>> So far I'm +1 on the proposal, and I like the second iteration of it.
>> Except that I'm really sad to see the __match__ protocol gone.
>
>
> It will be back, just not in 3.10. We need more experience with how match/case are actually used to design the right `__match__` protocol.

Makes sense.

>
>>
>> Quoting the PEP:
>>
>> > One drawback of this protocol is that the arguments to __match__ would be expensive to construct, and could not be pre-computed due to the fact that, because of the way names are bound, there are no real constants in Python.
>
>
> Note: That's not referring to the `__match__` protocol from version 1 of the PEP, but to a hypothetical (and IMO sub-optimal) `__match__` protocol that was discussed among the authors prior to settling on the protocol from version 1.
>
>>
>> While it's not possible to precompute the arguments ahead of time, it
>> certainly should be possible to cache them similarly to how I
>> implemented global names lookup cache in CPython. That should
>> alleviate this particular performance consideration entirely.
>
>
> Where's that global names lookup cache? I seem to have missed its introduction. (Unless you meant PEP 567?)

Here are the related bpos of where Inada-san and I worked on this:

https://bugs.python.org/issue28158
https://bugs.python.org/issue26219

>
>>
>> Having __match__ would allow some really interesting use cases. For
>> example, for binary protocol parsers it would be possible to replicate
>> erlang approach, e.g.:
>>
>> match buffer:
>> case Frame(char('X'), len := UInt32(), flags := Bits(0, 1, flag1,
>> flag2, 1, 1))
>>
>> would match a Frame of message type 'X', capture its length, and
>> extract two bit flags. This perhaps isn't the greatest example of how
>> a full matching protocol could be used, but it's something that I
>> personally wanted to implement.
>
>
> I see, you'd want the *types* of the arguments to be passed into `Frame.__match__`. That's interesting, although I have a feeling that if I had a real use case like this I'd probably be able to come up with a better DSL for specifying messages than this.

Yeah, it's an open question if this is a good idea or not. FWIW here's
a relevant quick erlang tutorial:
https://dev.to/l1x/matching-binary-patterns-11kh that shows what it
looks like in erlang (albeit the syntax is completely alien to
Python).

Yury
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-leave@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/LMWGQX4RNZE2WS34OM6QU7SLFVQIKYT3/
Code of Conduct: http://python.org/psf/codeofconduct/
Re: PEP 622 version 2 (Structural Pattern Matching) [ In reply to ]
On 7/17/2020 7:23 AM, emmanuel.coirier@caissedesdepots.fr wrote:
> Hello everyone,
>
> I'm sorry if my proposition has already being said, or even withdrawn,
> but I think that capture variables shouldn't be as implicit as they
> are now.

> I've looked at the PEP very quickly, jumping on the examples to have
> a taste and an idea of what was going here. I saw a new kind of control
> structure based on structural pattern matching (pattern based on
> classes or compositions of classes to make it short). A very good
> idea, emphasized by Tobias Kohn ("Another take on PEP 622") is that
> pattern matching eases the writting of code based on matching such
> structures, and that capturing values stored inside of these
> structures at the match time really eases the writting of the code
> associated with this match.

A major points of Kohn's post is that 'case' is analogous to 'def' and
match lists are analogous to parameter lists. In parameter lists,
untagged simple names ('parameter names') are binding targets.
Therefore, untagged simple names in match lists, let us call them 'match
names' should be also. I elaborated on this in my response to Tobias.

--
Terry Jan Reedy
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-leave@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/L62PAUPNVPZ47SNSMWOW2O3WRTZ3CAHI/
Code of Conduct: http://python.org/psf/codeofconduct/
Re: PEP 622 version 2 (Structural Pattern Matching) [ In reply to ]
On Fri, 17 Jul 2020, Ethan Furman wrote:

> The problem with any kind of sigil/keyword is that it becomes line noise --
> we would have to train ourselves to ignore them in order to see the structure
> and variables we are actually interested in. Once we become adept at ignoring
> them, we will again have difficulties when debugging as we won't easily see
> them.
>
> Besides which, the problem is solved:
>
> - namespace.var is a lookup
> - var is a store

Regardless how hard this is being pushed, I beg to disagree.
Matching is easy to think of as an extension of destructuring assignment,
and could easily be that, if we just don't introduce incompatible rules.

Everything currently allowed in an assignment is a store,
so it follows that the markup for lookups must be something that is
not currently allowed in an assignment.

Besides literal constants, my preference is for ``` == x ```,
with the obvious opening for future extension.

/Paul
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-leave@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/GASEWDEUNW7WNEDRD4JBF2HJ3AU26OJY/
Code of Conduct: http://python.org/psf/codeofconduct/
Re: PEP 622 version 2 (Structural Pattern Matching) [ In reply to ]
Terry Reedy wrote:

> A major points of Kohn's post is that 'case' is analogous to 'def' and
> match lists are analogous to parameter lists. In parameter lists,

I'm sorry to disagree, but match lists share very few things in common with today's parameters list, and introduce a full new concept of "matching" vs "binding/capturing" that doesn't exists with the function definition.

> untagged simple names ('parameter names') are binding targets.
> Therefore, untagged simple names in match lists, let us call them 'match
> names' should be also. I elaborated on this in my response to Tobias.

This approach, for me, seems to come from functionnal languages where pattern matching is a thing. The proposed "match" clause tends to mimic this approach, and it can be a good thing. But the Python's function definition has not been inspired by functionnal programming from the ground, and I think it would be an error to reason this way, because people not used to pattern matching in functionnal programming won't understand anything (imagine that comprehension lists are a big thing for many learners). That's why I think reasonning in such a theorical point of view will leads many python developpers to a dead end.
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-leave@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/AENMRD23UGV6D5KI25RSQSCJ3YGCGBUY/
Code of Conduct: http://python.org/psf/codeofconduct/
Re: PEP 622 version 2 (Structural Pattern Matching) [ In reply to ]
Ethan Furman wrote:
> The problem with any kind of sigil/keyword is that it becomes line noise
> -- we would have to train ourselves to ignore them in order to see the
> structure and variables we are actually interested in. Once we become

Every syntax element can become noise once we're used to it. This is how Groovy is built from Java : they removed everything that can be removed, and still be "understandable" by the compiler. The result is the language being counter intuitive for people that don't do Groovy everyday... Can I write thing like this ? Seems to work... And with that ? Works too, but I don't know if it produces the same effect...

We can also think about syntax elements as strucural elements like pillars, helping the thought to elaborate while reading the code. Pillars are constraints for people in a building (they block your view, you have to bypass them, ...), but they helps building bigger constructions, and we're all used to them.

In this slightly modified example from the PEP :

match entree[-1]:
case Sides.SPAM:
response = "Have you got anything without Spam?"
case "letuce":
response = "blablabla"
case side:
response = f"Well, could I have their Spam instead of the {side} then?"
case 1542 | "plop":
response = "blablabla2"

It's difficult for someone not mastering this feature to see immediatly that "side" will get it's value changed and that the last case will never match.

match entree[-1]:
case Sides.SPAM:
response = "Have you got anything without Spam?"
case "letuce":
response = "blablabla"
case side=:
response = f"Well, could I have their Spam instead of the {side} then?"
case 1542 | "plop":
response = "blablabla2"

Here we immediatly see that the first two cases don't work in the same way as the third, because there is "something more". It will even maybe indicate that the last case is useless...

> adept at ignoring them, we will again have difficulties when debugging
> as we won't easily see them.
> Besides which, the problem is solved:
>
> namespace.var is a lookup
> var is a store

These rules can't be deduced from a few examples, or from experience from other languages. You have to explicitly learn them. Since newcomers won't propably learn them first (if at all), they won't understand how it works, and they will propably introduce bugs hard to debug. They'll think it's a kind of "swith case" new construct, and will use it that way, completly ignoring the "capturing" property that shows in some cases and not in others.

match entree[-1]:
case Sides.SPAM:
# newcomers will understand that entree[-1] == Sides.SPAM and write the code they need

SPAM = "spam"
match entree[-1]:
case SPAM:
# newcomers will understand that entree[-1] == "spam" and write the code they need
# ignoring that now, in the following code, SPAM == anything but "spam"
# introducing a bug anywhere in the following code where SPAM is expected to hold the
# initial value

Only a unit test case that test that SPAM has changed can detect this kind of bug. Generally speaking, unit test cases don't test values of "constants" before and after a test case. So it won't even help.

Here, we can argue that match is not a "switch case" like syntax, but newcomers from C, Java, Javascript, whatever WILL use it like a "switch case", and WILL read code where it will be used like that. Even if it's not the main use case, it will be used for that, because of 50 years of history of C that we can't ignore. Adding a "=" or something else will at least ring a bell.

We can argue that constants should be namespaced, but is it a general way of doing ? People can write "from module import SPAM" or "import module; module.SPAM". This is equivalent, but in one case, it may introduce a bug.

Do not forget that Python will be used by many more newcomers, new learners, new developers, data scientists, people with unknow backgrounds, and perhaps few, or no experience in programming. IMHO Python strength is that it's syntax is easy to learn because it is easy to deduce. The some rules that are counter-intuitive like the "else" clause for the loops can't cause any harm if misused because their misuse is detected immediatly, and we can avoid writing them (and most people do).

On the other hand, "capturing" variables mixed with "match" variables is counter-intuitive unless you explicitly learn the rules. You can't deduce it (there rules don't exist anywhere else). This feature is central of the PEP and will be used, and will introduce subtle bugs when misused.

That's why I consider the rules you stated is not the right way for this feature, and that we should be explicit.
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-leave@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/HQLSHN4IJSN36I4R6D6DUVDTJTYEZW4O/
Code of Conduct: http://python.org/psf/codeofconduct/
Re: PEP 622 version 2 (Structural Pattern Matching) [ In reply to ]
On Sat, Jul 18, 2020 at 3:46 AM Terry Reedy <tjreedy@udel.edu> wrote:

>
> A major points of Kohn's post is that 'case' is analogous to 'def' and
> match lists are analogous to parameter lists. In parameter lists,
> untagged simple names ('parameter names') are binding targets.
> Therefore, untagged simple names in match lists, let us call them 'match
> names' should be also. I elaborated on this in my response to Tobias.
>
>
There are indeed analogous aspects, although not in the most
straightfoward/obvious ways. Still, perhaps even more so than there is
analogy with assignment targets.

This is related to one of my concerns regarding PEP 622. It may be tempting
to see pattern matching as a form of assignment. However, that is quite a
stretch, both conceptually and as a future direction. There is no way these
'match expressions' could be allowed in regular assignments – the way names
are treated just needs to be different. And allowing them in walrus
assignments doesn't make much sense either.

Conceptually, it is strange to call this match operation an assignment.
Most of the added power comes from checking that the object has a certain
structure or contents – and in many cases, that is the only thing it does!
As a (not always) handy side product, it is also able to assign things to
specified targets. Even then, the whole pattern is not assigned to, only
parts of it are.

In mathematics, assignment (definition) and re-assignment is often denoted
with the same sign as equality/identity, because it is usually clear from
the context, which one is in question. Usually, however, it matters which
one is in question. Therefore, as we well know, we have = for assignment,
== for equality, and := to emphasize assignment. Matching is closer to ==,
or almost :==.

So, in many ways, is the assignment that is special, not the matching. It
is also the main thing that differentiates this from the traditional
switch–case construct, which the proposed syntax certainly resembles.

—Koos
Re: PEP 622 version 2 (Structural Pattern Matching) [ In reply to ]
On Sat, Jul 18, 2020 at 09:25:45AM -0000, emmanuel.coirier@caissedesdepots.fr wrote:

> This approach, for me, seems to come from functionnal languages where
> pattern matching is a thing. The proposed "match" clause tends to
> mimic this approach, and it can be a good thing. But the Python's
> function definition has not been inspired by functionnal programming
> from the ground, and I think it would be an error to reason this way,
> because people not used to pattern matching in functionnal programming
> won't understand anything (imagine that comprehension lists are a big
> thing for many learners).

It is true that beginners sometimes struggle a bit to grok comprehension
syntax. I know I did.

And yet, despite that, comprehensions have turned out to be one of the
most powerful and popular features of Python, sometimes *too* popular.
It is sometimes hard to convince both beginners and even experienced
devs that comprehensions are not the only tool in their toolbox, and not
every problem is a nail.

You say: "people not used to pattern matching in functionnal programming
won't understand anything" but people using Haskell weren't born knowing
the language. They had to learn it.

It's been sometimes said that functional programmers are smarter, elite
programmers a level above the average OOP or procedural programmer, but
that's mostly said by functional programmers :-) and I'm not entirely
sure that its true. In any case, I don't think that any (actual or
imaginary) gap between the ability of the average Haskell programmer and
the average Python programmer is so great that we should dismiss pattern
matching as beyond the grasp of Python coders.

In any case, functional languages like Haskell, F# and ML are not the
only languages with pattern matching. Non-FP languages like C#, Swift,
Rust and Scala have it, and even Java has an extension providing pattern
matching:

http://tom.loria.fr/wiki/index.php/Main_Page


--
Steven
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-leave@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/JC4HWW6DAJAWZLJAW6ACBT5IARA25M2Q/
Code of Conduct: http://python.org/psf/codeofconduct/
Re: PEP 622 version 2 (Structural Pattern Matching) [ In reply to ]
On Sat, Jul 18, 2020 at 3:29 AM <emmanuel.coirier@caissedesdepots.fr> wrote:

> > adept at ignoring them, we will again have difficulties when debugging
> > as we won't easily see them.
> > Besides which, the problem is solved:
> >
> > namespace.var is a lookup
> > var is a store
>
> These rules can't be deduced from a few examples, or from experience from
> other languages. You have to explicitly learn them. Since newcomers won't
> propably learn them first (if at all), they won't understand how it works,
> and they will propably introduce bugs hard to debug. They'll think it's a
> kind of "swith case" new construct, and will use it that way, completly
> ignoring the "capturing" property that shows in some cases and not in
> others.
>
> match entree[-1]:
> case Sides.SPAM:
> # newcomers will understand that entree[-1] == Sides.SPAM and
> write the code they need
>
> SPAM = "spam"
> match entree[-1]:
> case SPAM:
> # newcomers will understand that entree[-1] == "spam" and
> write the code they need
> # ignoring that now, in the following code, SPAM == anything
> but "spam"
> # introducing a bug anywhere in the following code where SPAM
> is expected to hold the
> # initial value
>

If a constant's actually constant, as in

SPAM: Final = "spam"

then it'll throw an error. Likewise, the first time it does something
totally unexpected like insert something into what they thought held a
match pattern, it'll break their initial assumptions and hopefully get them
to read the documentation, to form a more accurate mental model.

<http://python.org/psf/codeofconduct/>As long as

> namespace.var is a lookup
> var is a store

is big, bold, and front & center in the docs, I think everyone will catch
on very quickly and wrap their vars in a class, even if they never use it
for more than a glorified switch-case. Designing an entire feature around
what someone who's never encountered it before thinks it might do doesn't
seem useful, since anyone could bring any number of assumptions.

-Em
Re: PEP 622 version 2 (Structural Pattern Matching) [ In reply to ]
On 7/18/2020 6:23 AM, emmanuel.coirier@caissedesdepots.fr wrote:
> Ethan Furman wrote:
>> The problem with any kind of sigil/keyword is that it becomes line noise
>> -- we would have to train ourselves to ignore them in order to see the
>> structure and variables we are actually interested in. Once we become

[snip much]

> On the other hand, "capturing" variables mixed with "match" variables is counter-intuitive unless you explicitly learn the rules. You can't deduce it (there rules don't exist anywhere else). This feature is central of the PEP and will be used, and will introduce subtle bugs when misused.
>
> That's why I consider the rules you stated is not the right way for this feature, and that we should be explicit.

It seems to me that whether one expects simple names in case headers to
be sources or targets depends on how one analogizes the match code in
case headers. If one sees it as analogous to imperative elif
conditions, where names are value sources, then one likely expects that.
If one sees match code as analogous to target or parameter lists,
where names declare binding targets, then one like expect that behavior
instead.

Both analogies are inexact because match code needs to have both sources
and targets. Different people will have different preferences and
expectations.

I happen to prefer the parameter list analogy because conditions are
executable expressions while match code is not and by intention is
partly to mostly declarative, with the implementation in logic and
expressions left to the compiler.

--
Terry Jan Reedy
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-leave@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/LJHGWWKYBCAK64AYHISY3JC63VKEOI2G/
Code of Conduct: http://python.org/psf/codeofconduct/
Re: PEP 622 version 2 (Structural Pattern Matching) [ In reply to ]
On 18/07/2020 11:23, emmanuel.coirier@caissedesdepots.fr wrote:
> Ethan Furman wrote:
>> The problem with any kind of sigil/keyword is that it becomes line noise
>> -- we would have to train ourselves to ignore them in order to see the
>> structure and variables we are actually interested in. Once we become
> Every syntax element can become noise once we're used to it. This is how Groovy is built from Java : they removed everything that can be removed, and still be "understandable" by the compiler. The result is the language being counter intuitive for people that don't do Groovy everyday... Can I write thing like this ? Seems to work... And with that ? Works too, but I don't know if it produces the same effect...
>
> We can also think about syntax elements as strucural elements like pillars, helping the thought to elaborate while reading the code. Pillars are constraints for people in a building (they block your view, you have to bypass them, ...), but they helps building bigger constructions, and we're all used to them.
>
> In this slightly modified example from the PEP :
>
> match entree[-1]:
> case Sides.SPAM:
> response = "Have you got anything without Spam?"
> case "letuce":
> response = "blablabla"
> case side:
> response = f"Well, could I have their Spam instead of the {side} then?"
> case 1542 | "plop":
> response = "blablabla2"
>
> It's difficult for someone not mastering this feature to see immediatly that "side" will get it's value changed and that the last case will never match.

+1

>
> match entree[-1]:
> case Sides.SPAM:
> response = "Have you got anything without Spam?"
> case "letuce":
> response = "blablabla"
> case side=:
> response = f"Well, could I have their Spam instead of the {side} then?"
> case 1542 | "plop":
> response = "blablabla2"
>
> Here we immediatly see that the first two cases don't work in the same way as the third, because there is "something more". It will even maybe indicate that the last case is useless...
>
>> adept at ignoring them, we will again have difficulties when debugging
>> as we won't easily see them.
>> Besides which, the problem is solved:
>>
>> namespace.var is a lookup
>> var is a store
> These rules can't be deduced from a few examples, or from experience from other languages. You have to explicitly learn them.

+1

> Since newcomers won't propably learn them first (if at all), they won't understand how it works, and they will propably introduce bugs hard to debug. They'll think it's a kind of "swith case" new construct, and will use it that way, completly ignoring the "capturing" property that shows in some cases and not in others.
>
> match entree[-1]:
> case Sides.SPAM:
> # newcomers will understand that entree[-1] == Sides.SPAM and write the code they need
>
> SPAM = "spam"
> match entree[-1]:
> case SPAM:
> # newcomers will understand that entree[-1] == "spam" and write the code they need
> # ignoring that now, in the following code, SPAM == anything but "spam"
> # introducing a bug anywhere in the following code where SPAM is expected to hold the
> # initial value
>
> Only a unit test case that test that SPAM has changed can detect this kind of bug. Generally speaking, unit test cases don't test values of "constants" before and after a test case. So it won't even help.
>
> Here, we can argue that match is not a "switch case" like syntax, but newcomers from C, Java, Javascript, whatever WILL use it like a "switch case", and WILL read code where it will be used like that. Even if it's not the main use case, it will be used for that, because of 50 years of history of C that we can't ignore. Adding a "=" or something else will at least ring a bell.
>
> We can argue that constants should be namespaced, but is it a general way of doing ? People can write "from module import SPAM" or "import module; module.SPAM". This is equivalent, but in one case, it may introduce a bug.
>
> Do not forget that Python will be used by many more newcomers, new learners, new developers, data scientists, people with unknow backgrounds, and perhaps few, or no experience in programming. IMHO Python strength is that it's syntax is easy to learn because it is easy to deduce. The some rules that are counter-intuitive like the "else" clause for the loops can't cause any harm if misused because their misuse is detected immediatly, and we can avoid writing them (and most people do).
>
> On the other hand, "capturing" variables mixed with "match" variables is counter-intuitive unless you explicitly learn the rules. You can't deduce it (there rules don't exist anywhere else). This feature is central of the PEP and will be used, and will introduce subtle bugs when misused.
>
> That's why I consider the rules you stated is not the right way for this feature, and that we should be explicit.
+1.  Explicit is better than implicit.
> _______________________________________________
> Python-Dev mailing list -- python-dev@python.org
> To unsubscribe send an email to python-dev-leave@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/HQLSHN4IJSN36I4R6D6DUVDTJTYEZW4O/
> Code of Conduct: http://python.org/psf/codeofconduct/
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-leave@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/W7BZRTNY6TI5WHC5YRBOZOMDVSNEOGC2/
Code of Conduct: http://python.org/psf/codeofconduct/
Re: PEP 622 version 2 (Structural Pattern Matching) [ In reply to ]
Steven D'Aprano wrote:
[...]
> In any case, functional languages like Haskell, F# and ML are not the
> only languages with pattern matching. Non-FP languages like C#, Swift,
> Rust and Scala have it, and even Java has an extension providing pattern
> matching:
> http://tom.loria.fr/wiki/index.php/Main_Page

I'm not against pattern matching at all. I think it's a very nice feature, but that one of its behavior which is variable capturing should be made more explicit, following the rules of the Zen of Python.

> It's been sometimes said that functional programmers are smarter, elite
> programmers a level above the average OOP or procedural programmer, but
> that's mostly said by functional programmers :-)

I would say there are fewer of them :-)

--
Emmanuel
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-leave@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/RMUF5Q6B3UKPK67FB5ALQYILPZE2JJGZ/
Code of Conduct: http://python.org/psf/codeofconduct/
Re: PEP 622 version 2 (Structural Pattern Matching) [ In reply to ]
Emily Bowman wrote:

> SPAM: Final = "spam"
> then it'll throw an error. Likewise, the first time it does something
> totally unexpected like insert something into what they thought held a
> match pattern, it'll break their initial assumptions and hopefully get them
> to read the documentation, to form a more accurate mental model.

Currently, the following example is working without any error or warning on the current Guido's build. I'm aware that it is not the final version, but I didn't see anything for now guarding Final decorated values to be overwritten at runtime (either by an affectation or by a case clause).

from typing import Final
FIVE_VALUE: Final = 5

a = (7, 8)
match a:
case (FIVE_VALUE, 8):
print("in five value clause")
case _:
print("in default clause")

print(f"Value of FIVE_VALUE: {FIVE_VALUE}")

But I concede overwriting names that are Final could at least throw some warnings.

> As long as
> > namespace.var is a lookup
> > var is a store
> is big, bold, and front & center in the docs, I think everyone will catch
> on very quickly and wrap their vars in a class, even if they never use it
> for more than a glorified switch-case.

My point is a bit deeper. I consider these rules a bit clumsy. I've undestood why they have been designed that way, but they didn't look pythonic. Like if scaffolding was still there.

> Designing an entire feature around
> what someone who's never encountered it before thinks it might do doesn't
> seem useful, since anyone could bring any number of assumptions.

I'm sorry to disagree. Apple has built its brand on the fact that you didn't need the doc to succesfully use their products. I don't think that all features of the langage have to be that obvious, but the first look by some random dev should help them catch the thing, and avoid such a pitfall.

--
Emmanuel
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-leave@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/6KDEVVVWBF57YQV3FI5HHDTKGJ5MCM6Y/
Code of Conduct: http://python.org/psf/codeofconduct/
Re: PEP 622 version 2 (Structural Pattern Matching) [ In reply to ]
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:

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


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.

https://www.python.org/dev/peps/pep-0622/#alternatives-for-constant-value-pattern
is nominally about this problem, but it doesn't even *mention* the single
biggest benefit of putting a common prefix on value constraints: it leaves
the door open to unifying the lvalue syntax again in the future by keeping
the proposed match case syntax a strict superset of the existing assignment
target syntax, rather than partially conflicting with it.

More incidentally, the latest write-up also leaves out "?" as a suggested
constraint value prefix, when that's the single character prefix that best
implies the question "Does the runtime value at this position equal the
result of this value constraint expression?" without having any other
existing semantic implications in Python.

Cheers,
Nick.

P.S. I feel I should mention that the other reason I like "?" as a
potential prefix for value constraints is that if we require it for all
value constraint expressions (both literals and name lookups) I believe it
could offer a way to unblock the None-aware expressions PEP by reframing
that PEP as a shorthand for particular case matches.

None coalescence ("a ?? b") for example:

match a:
case ?None:
_expr_result = b
case _match:
_expr_result = _match

Or a None-severing attribute lookup ("a?.b"):

_match_expr = a
match _match_expr:
case ?None:
_expr_result = _match_expr
case _match:
_expr_result = _match.b

Since these operations would be defined in terms of *equality* (as per PEP
622), rather than identity, it would also allow other sentinels to benefit
from the None-aware shorthand by defining themselves as being equal to None.


On Thu., 9 Jul. 2020, 1:07 am Guido van Rossum, <guido@python.org> wrote:

> Today I’m happy (and a little trepidatious) to announce the next
> version of PEP 622, Pattern Matching. As authors we welcome Daniel F
> Moisset in our midst. Daniel wrote a lot of the new text in this
> version, which introduces the subject matter much more gently than the
> first version did. He also convinced us to drop the `__match__`
> protocol for now: the proposal stands quite well without that kind of
> extensibility, and postponing it will allow us to design it at a later
> time when we have more experience with how `match` is being used.
>
> That said, the new version does not differ dramatically in what we
> propose. Apart from dropping `__match__` we’re dropping the leading
> dot to mark named constants, without a replacement, and everything
> else looks like we’re digging in our heels. Why is that? Given the
> firestorm of feedback we received and the numerous proposals (still
> coming) for alternative syntax, it seems a bad tactic not to give up
> something more substantial in order to get this proposal passed. Let
> me explain.
>
> Language design is not like politics. It’s not like mathematics
> either, but I don’t think this situation is at all similar to
> negotiating a higher minimum wage in exchange for a lower pension,
> where you can definitely argue about exactly how much lower/higher
> you’re willing to go. So I don’t think it’s right to propose making
> the feature a little bit uglier just to get it accepted.
>
> Frankly, 90% of the issue is about what among the authors we’ve dubbed
> the “load/store” problem (although Tobias never tires to explain that
> the “load” part is really “load-and-compare”). There’s a considerable
> section devoted to this topic in the PEP, but I’d like to give it
> another try here.
>
> In case you’ve been avoiding python-dev lately, the problem is
> this. Pattern matching lets you capture values from the subject,
> similar to sequence unpacking, so that you can write for example
> ```
> x = range(4)
> match x:
> case (a, b, *rest):
> print(f"first={a}, second={b}, rest={rest}") # 0, 1, [2, 3]
> ```
> Here the `case` line captures the contents of the subject `x` in three
> variables named `a`, `b` and `rest`. This is easy to understand by
> pretending that a pattern (i.e., what follows `case`) is like the LHS
> of an assignment.
>
> However, in order to make pattern matching more useful and versatile,
> the pattern matching syntax also allows using literals instead of
> capture variables. This is really handy when you want to distinguish
> different cases based on some value, for example
> ```
> match t:
> case ("rect", real, imag):
> return complex(real, imag)
> case ("polar", r, phi):
> return complex(r * cos(phi), r * sin(phi))
> ```
> You might not even notice anything funny here if I didn’t point out
> that `"rect"` and `"polar"` are literals -- it’s really quite
> natural for patterns to support this once you think about it.
>
> The problem that everybody’s been concerned about is that Python
> programmers, like C programmers before them, aren’t too keen to have
> literals like this all over their code, and would rather give names to
> the literals, for example
> ```
> USE_POLAR = "polar"
> USE_RECT = "rect"
> ```
> Now we would like to be able to replace those literals with the
> corresponding names throughout our code and have everything work like
> before:
> ```
> match t:
> case (USE_RECT, real, imag):
> return complex(real, imag)
> case (USE_POLAR, r, phi):
> return complex(r * cos(phi), r * sin(phi))
> ```
> Alas, the compiler doesn’t know that we want `USE_RECT` to be a
> constant value to be matched while we intend `real` and `imag` to be
> variables to be given the corresponding values captured from the
> subject. So various clever ways have been proposed to distinguish the
> two cases.
>
> This discussion is not new to the authors: before we ever published
> the first version of the PEP we vigorously debated this (it is Issue 1
> in our tracker!), and other languages before us have also had to come
> to grips with it. Even many statically compiled languages! The reason
> is that for reasons of usability it’s usually deemed important that
> their equivalent of `case` auto-declare the captured variables, and
> variable declarations may hide (override) like-named variables in
> outer scopes.
>
> Scala, for example, uses several different rules: first, capture
> variable names must start with a lowercase letter (so it would
> handle the above example as intended); next, capture variables
> cannot be dotted names (like `mod.var`); finally, you can enclose any
> variable in backticks to force the compiler to see it as a load
> instead of a store. Elixir uses another form of markup for loads: `x`
> is a capture variable, but `^x` loads and compares the value of `x`.
>
> There are a number of dead ends when looking for a solution that works
> for Python. Checking at runtime whether a name is defined or not is
> one of these: there are numerous reasons why this could be confusing,
> not the least of which being that the `match` may be executed in a
> loop and the variable may already be bound by a previous
> iteration. (True, this has to do with the scope we’ve adopted for
> capture variables. But believe me, giving each case clause its own
> scope is quite horrible by itself, and there are other
> action-at-a-distance effects that are equally bad.)
>
> It’s been proposed to explicitly state the names of the variables
> bound in a header of the `match` statement; but this doesn’t scale
> when the number of cases becomes larger, and requires users to do
> bookkeeping the compiler should be able to do. We’re really looking
> for a solution that tells you when you’re looking at an individual
> `case` which variables are captured and which are used for
> load-and-compare.
>
> Marking up the capture variables with some sigil (e.g. `$x` or `x?`)
> or other markup (e.g. backticks or `<x>`) makes this common case ugly
> and inconsistent: it’s unpleasant to see for example
> ```
> case %x, %y:
> print(x, y)
> ```
> No other language we’ve surveyed uses special markup for capture
> variables; some use special markup for load-and-compare, so we’ve
> explored this. In fact, in version 1 of the PEP our long-debated
> solution was to use a leading dot. This was however boohed off the
> field, so for version 2 we reconsidered. In the end nothing struck our
> fancy (if `.x` is unacceptable, it’s unclear why `^x` would be any
> better), and we chose a simpler rule: named constants are only
> recognized when referenced via some namespace, such as `mod.var` or
> `Color.RED`.
>
> We believe it’s acceptable that things looking like `mod.var` are
> never considered capture variables -- the common use cases for `match`
> are such that one would almost never want to capture into a different
> namespace. (Just like you very rarely see `for self.i in …` and never
> `except E as scope.var` -- the latter is illegal syntax and sets a
> precedent.)
>
> One author would dearly have seen Scala’s uppercase rule adopted, but
> in the end was convinced by the others that this was a bad idea, both
> because there’s no precedent in Python’s syntax, and because many
> human languages simply don’t make the distinction between lowercase
> and uppercase in their writing systems.
>
> So what should you do if you have a local variable (say, a function
> argument) that you want to use as a value in a pattern? One solution
> is to capture the value in another variable and use a guard to compare
> that variable to the argument:
> ```
> def foo(x, spam):
> match x:
> case Point(p, q, context=c) if c == spam:
> # Match
> ```
> If this really is a deal-breaker after all other issues have been
> settled, we could go back to considering some special markup for
> load-and-compare of simple names (even though we expect this case to
> be very rare). But there’s no pressing need to decide to do this now
> -- we can always add new markup for this purpose in a future version,
> as long as we continue to support dotted names without markup,
> since that *is* a commonly needed case.
>
> There’s one other issue where in the end we could be convinced to
> compromise: whether to add an `else` clause in addition to `case
> _`. In fact, we probably would already have added it, except for one
> detail: it’s unclear whether the `else` should be aligned with `case`
> or `match`. If we are to add this we would have to ask the Steering
> Council to decide for us, as the authors deadlocked on this question.
>
> Regarding the syntax for wildcards and OR patterns, the PEP explains
> why `_` and `|` are the best choices here: no other language surveyed
> uses anything but `_` for wildcards, and the vast majority uses `|`
> for OR patterns. A similar argument applies to class patterns.
>
> If you've made it so far, here are the links to check out, with an
> open mind. As a reminder, the introductory sections (Abstract,
> Overview, and Rationale and Goals) have been entirely rewritten and
> also serve as introduction and tutorial.
>
> - PEP 622: https://www.python.org/dev/peps/pep-0622/
> - Playground:
> https://mybinder.org/v2/gh/gvanrossum/patma/master?urlpath=lab/tree/playground-622.ipynb
>
> --
> --Guido van Rossum (python.org/~guido)
> *Pronouns: he/him **(why is my pronoun here?)*
> <http://feministing.com/2015/02/03/how-using-they-as-a-singular-pronoun-can-change-the-world/>
> _______________________________________________
> Python-Dev mailing list -- python-dev@python.org
> To unsubscribe send an email to python-dev-leave@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/LOXEATGFKLYODO5Y4JLSLAFXKIAMJVK5/
> Code of Conduct: http://python.org/psf/codeofconduct/
>
Re: PEP 622 version 2 (Structural Pattern Matching) [ In reply to ]
On Fri, 17 Jul 2020 at 12:28, Gustavo Carneiro <gjcarneiro@gmail.com> wrote:

>
>
> On Fri, 17 Jul 2020 at 12:26, <emmanuel.coirier@caissedesdepots.fr> wrote:
>
>> Hello everyone,
>> (...)
>> But... looking at the examples, it wasn't very obvious that some
>> variables were catching variables and some others were matching ones.
>> I then read in details some rules about how to discover what is a
>> captured variable. But I'm not sure everybody will do this...
>>
>> Zen of Python tells us that "explicit is better than implicit". I know
>> this is not a rule written in the stone, but I think here, it applies
>> very well.
>>
>>
I Also dislike the idea of undotted names being assigned, with not extra
visual clues,
and the scenario described by Emmanuel, in the other e-mail about
people changing variables when they think they are making a match
(essentially introducing the _same_ problem that `if (SPAM = 0):` had in C
which Python used to justify assignment not being an expression for over
20 years).

So, in adding to the bikeshed color possibilities, alongside
the "x=, y=" in this first e-mail or the "_ as x, _ as y" from Gustavo,
I present the possibility of making the Walrus mandatory for capture.
Maybe it is a bit "too much typing" - (Walrus will require 5-6 keystrokes
with the surrounding spaces), but I think the final look can be pleasantly
intuitive:

match my_point:
case (x := _, y := _) | Point2d(x := _, y := _):
return Point3d(x, y, 0)




> Guido said :
>> > We’re really looking
>> > for a solution that tells you when you’re looking at an individual
>> > case which variables are captured and which are used for
>> > load-and-compare.
>> >
>> > Marking up the capture variables with some sigil (e.g. $x or
>> > x?)
>> > or other markup (e.g. backticks or <x>) makes this common case ugly
>> > and inconsistent: it’s unpleasant to see for example
>> >
>> > case %x, %y:
>> > print(x, y)
>>
>> Guido talk about a "sigil", which seems to be a meaningless mark only
>> here to help the parser understand what the dev was writing.
>>
>> I propose that this "sigil" be the affectation mark : "=". Look :
>>
>> z = 42
>> match pt:
>> case x=, y=, z:
>> print(x, y, "z == 42")
>>
> (...)
Gustavo Carneiro <gjcarneiro@gmail.com> wrote:

> I kind of agree it is nicer to be more explicit. But somehow x= looks
> ugly. It occurred to me (and, again, apologies if already been mentioned),
> we might use the `as` keyword here.
>
> The example above would become:
>
> def make_point_3d(pt):
> match pt:
> case (as x, as y):
> return Point3d(x, y, 0)
> case (as x, as y, as z):
> return Point3d(x, y, z)
> case Point2d(as x, as y):
> return Point3d(x, y, 0)
> case Point3d(_, _, _):
> return pt
> case _:
> raise TypeError("not a point we support")
>
> If having "as x" as a standalone expression without anything to the left
> of "as" causes confusion, we could instead mandate the use of _ thus:
>
> case (_ as x, _ as y):
> return Point3d(x, y, 0)
>

1 2 3 4 5 6 7  View All