Mailing List Archive

1 2 3 4 5 6 7  View All
Re: PEP 622 version 2 (Structural Pattern Matching) [ In reply to ]
Just my 2 cents, I find it kind of annoying that the whole structure
requires two levels of indentation to actually reach the operational
code.
This would be a first in python.

I would prefer an option akin to if elif elif else where each block is
only one level deep.


On Wed, 8 Jul 2020 at 16:10, 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?)
> _______________________________________________
> 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/



--
Kind regards,

Stefano Borini
_______________________________________________
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/TG64UO5WGOHTYQ5U46E3KFG4YKWQBARE/
Code of Conduct: http://python.org/psf/codeofconduct/
Re: PEP 622 version 2 (Structural Pattern Matching) [ In reply to ]
On 7/10/2020 1:21 AM, Stefano Borini wrote:
> Just my 2 cents, I find it kind of annoying that the whole structure
> requires two levels of indentation to actually reach the operational
> code.
> This would be a first in python.
>
> I would prefer an option akin to if elif elif else where each block is
> only one level deep.
Me too.

That would also sidestep the dilemma of whether else: (if implemented)
should be indented like case: or like match: because they would be the same.

match:
    t
case ("rect", real, imag):
    return complex(real, imag)
case ("polar", r, phi):
    return complex( r* cos(phi), r*sin(phi)
else:
    return None

but it does make the match: block not a statement group, which was
disturbing to some.

On the other hand, this has a correspondence to:

try:
     throw expression
except (type of expression) as exc1:
     blah blah1
except (another type) as exc2:
    blah blah2
else:
    blah blah3

In fact, one _could_ wrap this whole feature into the try: syntax... the
match statement would be tried, and the cases would be special types of
exception handlers:

try:
    match expression
case ("rect", real, imag):
    return complex(real, imag)
case ("polar", r, phi):
    return complex( r* cos(phi), r*sin(phi)
else:
    return None

If the expression could fail to be calculated, one could have a mix of
except clauses also to catch those, rather than needing to wrap the
whole match expression in a separate try to handle that case [making the
nesting even deeper :( ]

There might even be a use for using case clauses to extend "normal"
exception handling, where the exception object could be tested for its
content as well as its class to have different handling.

try:
    raise Exception("msg", 35, things)
case Exception( x, "widgets"):
    blah blah 1
case Exception( x, "characters"):
    blah blah 2
else:
    blah blah 3

In this not-fully-thought-through scenario, maybe the keyword match
isn't even needed: "raise expression" could do the job, or they could be
aliases to signify intent.

In other words, a match expression would always "fail". The only
mismatch here is that it points out the difference between try-else and
match-else: try-else is executed if there is no failure, but if match
always fails, else would never be appropriate, and case _: would be.

In any case, it does seem there is a strong correlation between match
processing and try processing, that I didn't see during other
discussions of the possible structural similarities. "match 3 / 0:"
would clearly need to be wrapped in a try:

try:
    match x / y:
         case 43:
               print("wow, it is 43")
         case 22:
               print("22 seemed less likely than 43 for some reason")
        case _:
              print("You get what you get")
except ZeroDivisionError as exc:
    print(f"But sometimes you get an exception {exc}")

or:

try:
    raise x / y
case 43:
    print("wow, it is 43")
case 22:
    print("22 seemed less likely than 43 for some reason")
case exc := ZeroDivisionError:
    print(f"But sometimes you get an exception: {exc}")
case _:
    print("You get what you get")
_______________________________________________
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/GDP2KKB3SUWQZRSNTR5N36LXZ6HDS2QL/
Code of Conduct: http://python.org/psf/codeofconduct/
Re: PEP 622 version 2 (Structural Pattern Matching) [ In reply to ]
If we are still not certain about the exact language to describe match then I would ask if the 'case' token is really required. It seems that I would prefer

match expr:
pattern0:
block0
pattern1:
block1
.....
else:
blockdefault

where the else: clause is optional.

Also for me the unusual case is the assignment to names in the pattern and I would prefer that that be marked in some way; I didn't like .name, but ?name seems OK (or perhaps => name). Also the restriction that assigned vars should only occur once in a pattern seems wrong. I would regard it as an additional constraint on the match, but I do admit I don't fully understand what's allowed in patterns.

Please disregard if the above is totally stupid.
_______________________________________________
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/5SJY2HAT2CHG2BKYV4IZDZVM2BZILXTT/
Code of Conduct: http://python.org/psf/codeofconduct/
Re: PEP 622 version 2 (Structural Pattern Matching) [ In reply to ]
On Fri, 10 Jul 2020 at 10:33, Glenn Linderman <v+python@g.nevcal.com> wrote:

> On 7/10/2020 1:21 AM, Stefano Borini wrote:
> > Just my 2 cents, I find it kind of annoying that the whole structure
> > requires two levels of indentation to actually reach the operational
> > code.
> > This would be a first in python.
> >
> > I would prefer an option akin to if elif elif else where each block is
> > only one level deep.
> Me too.
>
> That would also sidestep the dilemma of whether else: (if implemented)
> should be indented like case: or like match: because they would be the
> same.
>
> match:
> t
> case ("rect", real, imag):
> return complex(real, imag)
> case ("polar", r, phi):
> return complex( r* cos(phi), r*sin(phi)
> else:
> return None
>
> but it does make the match: block not a statement group, which was
> disturbing to some.
>
> On the other hand, this has a correspondence to:
>
> try:
> throw expression
> except (type of expression) as exc1:
> blah blah1
> except (another type) as exc2:
> blah blah2
> else:
> blah blah3
>

The problem of the try...except structure, with less indentation, is that,
yes, it is OK for exceptions because normally you have 2 or 3 `except XXX`
clauses, therefore it is usually easy to follow, if the number of vertical
lines in the entire block of try-catch is low enough.

But I have had cases with catching many exception types, each with its own
block of 4 or 5 lines, adding up to a block of try-excepts that doesn't
even fit in a single window of my editor. In that case, I always have
wished for except clauses to be extra indented, to more easily distinguish
where the try..except block ends.

Therefore, I posit that the style of try...except indentation only works
where the number of cases is small.

But for the case of pattern matching, I expect the number of cases to be
matched to be a lot higher than exception handling cases. Having cases to
be matched be indented is, IMHO, a nice visual cue to help the reader
understand where the pattern matching block ends.


> In fact, one _could_ wrap this whole feature into the try: syntax... the
> match statement would be tried, and the cases would be special types of
> exception handlers:
>
> try:
> match expression
> case ("rect", real, imag):
> return complex(real, imag)
> case ("polar", r, phi):
> return complex( r* cos(phi), r*sin(phi)
> else:
> return None
>
> If the expression could fail to be calculated, one could have a mix of
> except clauses also to catch those, rather than needing to wrap the
> whole match expression in a separate try to handle that case [making the
> nesting even deeper :( ]
>
> There might even be a use for using case clauses to extend "normal"
> exception handling, where the exception object could be tested for its
> content as well as its class to have different handling.
>
> try:
> raise Exception("msg", 35, things)
> case Exception( x, "widgets"):
> blah blah 1
> case Exception( x, "characters"):
> blah blah 2
> else:
> blah blah 3
>
> In this not-fully-thought-through scenario, maybe the keyword match
> isn't even needed: "raise expression" could do the job, or they could be
> aliases to signify intent.
>
> In other words, a match expression would always "fail". The only
> mismatch here is that it points out the difference between try-else and
> match-else: try-else is executed if there is no failure, but if match
> always fails, else would never be appropriate, and case _: would be.
>
> In any case, it does seem there is a strong correlation between match
> processing and try processing, that I didn't see during other
> discussions of the possible structural similarities. "match 3 / 0:"
> would clearly need to be wrapped in a try:
>
> try:
> match x / y:
> case 43:
> print("wow, it is 43")
> case 22:
> print("22 seemed less likely than 43 for some reason")
> case _:
> print("You get what you get")
> except ZeroDivisionError as exc:
> print(f"But sometimes you get an exception {exc}")
>
> or:
>
> try:
> raise x / y
> case 43:
> print("wow, it is 43")
> case 22:
> print("22 seemed less likely than 43 for some reason")
> case exc := ZeroDivisionError:
> print(f"But sometimes you get an exception: {exc}")
> case _:
> print("You get what you get")
> _______________________________________________
> 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/GDP2KKB3SUWQZRSNTR5N36LXZ6HDS2QL/
> 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 ]
A thought about the indentation level of a speculated "else" clause...

Some people have argued that "else" should be at the outer level,
because that's the way it is in all the existing compound statements.

However, in those statements, all the actual code belonging to the
statement is indented to the same level:

if a:
....
elif b:
....
else:
....

^
|
Code all indented to this level

But if we were to indent "else" to the same level as "match",
the code under it would be at a different level from the rest.

match a:
case 1:
....
case 2:
....
else:
....
^ ^
| |
Code indented to two different levels

This doesn't seem right to me, because all of the cases, including
the else, are on the same footing semantically, just as they are in
an "if" statement.

--
Greg
_______________________________________________
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/ACH4QXCURTNEGKFQXEWET5NQ6DIABSQZ/
Code of Conduct: http://python.org/psf/codeofconduct/
Re: PEP 622 version 2 (Structural Pattern Matching) [ In reply to ]
> On 10 Jul 2020, Stefano Borini <stefano.borini@gmail.com> wrote:
>
> Just my 2 cents, I find it kind of annoying that the whole structure
> requires two levels of indentation to actually reach the operational
> code.
> This would be a first in python.
>
> I would prefer an option akin to if elif elif else where each block is
> only one level deep.


It very much depends on how you read it.

To me the proposed structure is like

with <expression> as <container>:
if <container> <match-op> <pattern>:

elif <container> <match-op> <pattern>:


and thus not really different
Re: PEP 622 version 2 (Structural Pattern Matching) [ In reply to ]
On Fri, 10 Jul 2020 at 12:08, Greg Ewing <greg.ewing@canterbury.ac.nz> wrote:
>
> A thought about the indentation level of a speculated "else" clause...
>
> Some people have argued that "else" should be at the outer level,
> because that's the way it is in all the existing compound statements.
>
> However, in those statements, all the actual code belonging to the
> statement is indented to the same level:
>
> if a:
> ....
> elif b:
> ....
> else:
> ....
>
> ^
> |
> Code all indented to this level
>
> But if we were to indent "else" to the same level as "match",
> the code under it would be at a different level from the rest.
>
> match a:
> case 1:
> ....
> case 2:
> ....
> else:
> ....
> ^ ^
> | |
> Code indented to two different levels
>
> This doesn't seem right to me, because all of the cases, including
> the else, are on the same footing semantically, just as they are in
> an "if" statement.

That's a good point - and sufficiently compelling that (if "align else
with match" ends up being the syntax) I'd always use "case _" rather
than else.

Equally, of course, it means that aligning else with match gives users
a choice of which indentation they prefer:

* Align with cases - use "case _"
* Align with match - use "else"

I've pretty much convinced myself that whatever happens, I'll ignore
else and just use "case _" everywhere (and mandate it in projects I
work on, where I have control over style).

One thought - what will tools like black do in the "case _ vs else"
debate? I can foresee some amusing flamewars if linters and formatters
end up preferring one form over the other...

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/IDCEBHXMCYYMONPUMD6QJDNMAFIFOYHJ/
Code of Conduct: http://python.org/psf/codeofconduct/
Re: PEP 622 version 2 (Structural Pattern Matching) [ In reply to ]
> On 10 Jul 2020, at 01:51, Jim Baker <jim.baker@python.org> wrote:
>
>
> On Thu, Jul 9, 2020 at 1:42 PM Eric Nieuwland <eric.nieuwland@gmail.com <mailto:eric.nieuwland@gmail.com>> wrote:
> Much of the discussion seems to focus on how to distinguish between a variable as a provider of a value and a variable as receiver of a matched value.
>
> In normal Python syntax a variable in an expression provides a value, please let’s keep that unchanged.
>
> For patterns, these are no different than parameters for a function (either a lambda expression or with `def`); or target assignments in unpacking assignments. So just like I wouldn't wonder where `a` and `b` materialized in the parameters for the function definition below
>
> def sum2(a, b):
> return a + b
>
> I think it will be straightforward to understand this in the context of a `case` using a capture pattern:
>
> match x:
> case (a, b):
> return a + b
> ...
>
> (This commonality between cases and function definitions is further used in Scala for example, but I don't see that approach for defining an idea of partial functions -- not like functools.partial functions! -- as being that useful in Python.)
>
>
> So it seems to me we should explicitly mark a variable to receive a matched value.
> I have seen ‘?’ suggested as a prefix to do this, ‘\’ would also do fine.
>
> This would solve the single variable issue, too:
> case foo:
> matches the value of ‘foo’, while
> case \foo:
> matches anything and stores it in ‘foo’.
>
>
> Explicit namespacing (if a constant) or using a guard (if a variable) seems to be the right solution, as Ethan demonstrated earlier. No need for . or ^ or \ or ... to disambiguate. Also it seems to me that structural pattern matching will build on two common usages of namespaces for constants:
>
> 1. Constants used from other modules are almost always used in the module namespace. Eg, socket.AF_UNIX or signal.SIGTERM.
> 2. New code often tends to use constants defined within an Enum namespace. Hopefully we will see more of this convention in usage.
>
> (Very much an aside: Interestingly with the socket module we see both used - it defines its constants with IntEnum and exports them traditionally. The namespace specifics it uses with IntEnum._convert_ to make this happen -- strictly speaking EnumMeta._convert, not documented, and a bit hard to follow -- might be possibly debatable, but it works out quite well in practice in providing backwards compatibility while continuing to work with a C source of these constants.)
>
> This would also mean
> case Point(x=\x, y=\y):
> should be used to obtain x and y from the Point instance.

This approach makes deeper nesting of the structure much more cumbersome, I think.

How to match Polygon(Point(x0,y0), Point(x1, y1), Point(x2, y2)) based on its structure?
And Polygon(Point(x0,y0), p1, Point(x2, y2))?
Re: PEP 622 version 2 (Structural Pattern Matching) [ In reply to ]
On Fri, Jul 10, 2020, 9:16 AM Eric Nieuwland <eric.nieuwland@gmail.com>
wrote:

>
> On 10 Jul 2020, at 01:51, Jim Baker <jim.baker@python.org> wrote:
>
> ...
> Explicit namespacing (if a constant) or using a guard (if a variable)
> seems to be the right solution, as Ethan demonstrated earlier. No need for
> . or ^ or \ or ... to disambiguate. Also it seems to me that structural
> pattern matching will build on two common usages of namespaces for
> constants:
>
> 1. Constants used from other modules are almost always used in the module
> namespace. Eg, socket.AF_UNIX or signal.SIGTERM.
> 2. New code often tends to use constants defined within an Enum namespace.
> Hopefully we will see more of this convention in usage.
>
> (Very much an aside: Interestingly with the socket module we see both used
> - it defines its constants with IntEnum and exports them traditionally. The
> namespace specifics it uses with IntEnum._convert_ to make this happen --
> strictly speaking EnumMeta._convert, not documented, and a bit hard to
> follow -- might be possibly debatable, but it works out quite well in
> practice in providing backwards compatibility while continuing to work with
> a C source of these constants.)
>
>
>> This would also mean
>> case Point(x=\x, y=\y):
>> should be used to obtain x and y from the Point instance.
>>
>
> This approach makes deeper nesting of the structure much more cumbersome,
> I think.
>
> How to match Polygon(Point(x0,y0), Point(x1, y1), Point(x2, y2)) based on
> its structure?
> And Polygon(Point(x0,y0), p1, Point(x2, y2))?
>
>
I'm just trying to describe what v2 of the PEP is trying to do and how it
then corresponds to a reasonable usage model. Sorry for any confusion.

So in your scenario above, Polygon and Point are used as class patterns (
https://www.python.org/dev/peps/pep-0622/#class-patterns). Consequently
they are treated accordingly and have that nice structural pattern matching
quality!

Earlier I was discussing constant patterns (
https://www.python.org/dev/peps/pep-0622/#constant-value-patterns), which
require they be namespaced in some way (a qualified name as it is described
in the PEP).

- Jim
Re: PEP 622 version 2 (Structural Pattern Matching) [ In reply to ]
One small question about this part of the PEP:

> For the most commonly-matched built-in types (bool, bytearray, bytes, dict,
float, frozenset, int, list, set, str, and tuple), a single positional
sub-pattern is allowed to be passed to the call. Rather than being matched
against any particular attribute on the subject, it is instead matched
against the subject itself.

Correct me if I'm wrong, but I don't think the PEP currently gives us a way
of enabling this behavior for classes not on this list. If so, would it be
worth adding a way?

It would help remove a special case and could come in handy when doing
things like creating my own custom data structures, for example. After all,
if `case dict(x)` makes x match the entire dict, it would be nice if I
could make `case MyCustomMapping(x)` behave in the same way to keep the
usage consistent.

We could maybe let classes opt-in to this behavior if they define
`__match_args__
= None`? Not sure if adding the extra "is None" check when doing the match
will introduce too much overhead though.

-- Michael


On Wed, Jul 8, 2020 at 8:06 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, Jul 10, 2020 at 9:54 AM Michael Lee <michael.lee.0x2a@gmail.com>
wrote:

> One small question about this part of the PEP:
>
> > For the most commonly-matched built-in types (bool, bytearray, bytes,
> dict, float, frozenset, int, list, set, str, and tuple), a single
> positional sub-pattern is allowed to be passed to the call. Rather than
> being matched against any particular attribute on the subject, it is
> instead matched against the subject itself.
>
> Correct me if I'm wrong, but I don't think the PEP currently gives us a
> way of enabling this behavior for classes not on this list. If so, would it
> be worth adding a way?
>
> It would help remove a special case and could come in handy when doing
> things like creating my own custom data structures, for example. After all,
> if `case dict(x)` makes x match the entire dict, it would be nice if I
> could make `case MyCustomMapping(x)` behave in the same way to keep the
> usage consistent.
>
> We could maybe let classes opt-in to this behavior if they define `__match_args__
> = None`? Not sure if adding the extra "is None" check when doing the
> match will introduce too much overhead though.
>
> -- Michael
>

Hi MIchael,

There is a way to do this. A class could do this:
```
class C:
__match_args__ = ["__self__"]

@property
def __self__(self):
return self
```
(You can use any name for `__self__`.)

I realize this isn't particularly pretty, but we feel it's better not to
add a custom `__match__` protocol at this time: The design space for that
is itself quite large, and we realized that almost all "easy" applications
could be had without it, while the "complicated" applications were all
trying to get the `__match__` protocol to do different things.

Also, beware that if your class does this, it is stuck with this form -- if
you replace `["__self__"]` with some other set of arguments, user code that
is matching against your class will presumably break.

--
--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 10/07/2020 12:33, Greg Ewing wrote:
> A thought about the indentation level of a speculated "else" clause...
>
> Some people have argued that "else" should be at the outer level,
> because that's the way it is in all the existing compound statements.
>
> However, in those statements, all the actual code belonging to the
> statement is indented to the same level:
>
>     if a:
>         ....
>     elif b:
>         ....
>     else:
>         ....
>
>         ^
>         |
>         Code all indented to this level
>
> But if we were to indent "else" to the same level as "match",
> the code under it would be at a different level from the rest.
>
>     match a:
>         case 1:
>             ....
>         case 2:
>             ....
>     else:
>         ....
>         ^   ^
>         |   |
>         Code indented to two different levels
>
> This doesn't seem right to me, because all of the cases, including
> the else, are on the same footing semantically, just as they are in
> an "if" statement.

I feel all those who aren't directly arguing against it are working off
the assumption that it is needed for match and case to have different
levels of indentation, but is this really true? Is there anything (bar
tradition or other subjective arguments) that speaks in favour of this,
especially in light of the fact that having the same indentation level
would also solve other problems?

A few emails ago I proposed something like this (and I'm probably only
the last one to do so amongst many), but if anyone made an argument
against it I must have missed it:

match:
    a
case 1:
    ...
case 2:
    ...
else:
    ...

(The a on a separate line being arguable.)

I think it would look neater, be reminiscent of the if/elif/else syntax
we're all familiar with, and solve the issue of where to indent the else.
Re: PEP 622 version 2 (Structural Pattern Matching) [ In reply to ]
Federico Salerno wrote:
> Is there anything (bar tradition or other subjective arguments) that speaks in favour of this, especially in light of the fact that having the same indentation level would also solve other problems? ...if anyone made an argument against it I must have missed it:

We spend a fair bit of time discussing this exact proposal in the PEP (I just searched for "indent"):

https://www.python.org/dev/peps/pep-0622/#use-a-flat-indentation-scheme
_______________________________________________
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/KLP6CTEVLYXVGBGBWCTUARV2KQAPYJVS/
Code of Conduct: http://python.org/psf/codeofconduct/
Re: PEP 622 version 2 (Structural Pattern Matching) [ In reply to ]
On 7/10/2020 3:15 AM, Gustavo Carneiro wrote:
>
>
> On Fri, 10 Jul 2020 at 10:33, Glenn Linderman <v+python@g.nevcal.com
> <mailto:v%2Bpython@g.nevcal.com>> wrote:
>
> On 7/10/2020 1:21 AM, Stefano Borini wrote:
> > Just my 2 cents, I find it kind of annoying that the whole structure
> > requires two levels of indentation to actually reach the operational
> > code.
> > This would be a first in python.
> >
> > I would prefer an option akin to if elif elif else where each
> block is
> > only one level deep.
> Me too.
>
> That would also sidestep the dilemma of whether else: (if
> implemented)
> should be indented like case: or like match: because they would be
> the same.
>
> match:
>      t
> case ("rect", real, imag):
>      return complex(real, imag)
> case ("polar", r, phi):
>      return complex( r* cos(phi), r*sin(phi)
> else:
>      return None
>
> but it does make the match: block not a statement group, which was
> disturbing to some.
>
> On the other hand, this has a correspondence to:
>
> try:
>       throw expression
> except (type of expression) as exc1:
>       blah blah1
> except (another type) as exc2:
>      blah blah2
> else:
>      blah blah3
>
>
> The problem of the try...except structure, with less indentation, is
> that, yes, it is OK for exceptions because normally you have 2 or 3
> `except XXX` clauses, therefore it is usually easy to follow, if the
> number of vertical lines in the entire block of try-catch is low enough.
>
> But I have had cases with catching many exception types, each with its
> own block of 4 or 5 lines, adding up to a block of try-excepts that
> doesn't even fit in a single window of my editor.  In that case, I
> always have wished for except clauses to be extra indented, to more
> easily distinguish where the try..except block ends.
>
> Therefore, I posit that the style of try...except indentation only
> works where the number of cases is small.
>
> But for the case of pattern matching, I expect the number of cases to
> be matched to be a lot higher than exception handling cases.  Having
> cases to be matched be indented is, IMHO, a nice visual cue to help
> the reader understand where the pattern matching block ends.

Actually, the current  if elseif elseif elseif else, used now because
Python has no switch/match/case, has exactly the same issue as you
describe as a problem with try if there were more cases... and if often
has more cases, just like match will.

So your concern seems nebulous. You may have wished for extra
indentation.... but it is simple to get more indentation: use 8 spaces
instead of 4. So if you really wanted it, you could have had it. It is
much harder to get less indentation when the language structures
prescribe it.

> In fact, one _could_ wrap this whole feature into the try:
> syntax... the
> match statement would be tried, and the cases would be special
> types of
> exception handlers:
>
> try:
>      match expression
> case ("rect", real, imag):
>      return complex(real, imag)
> case ("polar", r, phi):
>      return complex( r* cos(phi), r*sin(phi)
> else:
>      return None
>
> If the expression could fail to be calculated, one could have a
> mix of
> except clauses also to catch those, rather than needing to wrap the
> whole match expression in a separate try to handle that case
> [making the
> nesting even deeper :( ]
>
> There might even be a use for using case clauses to extend "normal"
> exception handling, where the exception object could be tested for
> its
> content as well as its class to have different handling.
>
> try:
>      raise Exception("msg", 35, things)
> case Exception( x, "widgets"):
>      blah blah 1
> case Exception( x, "characters"):
>      blah blah 2
> else:
>      blah blah 3
>
> In this not-fully-thought-through scenario, maybe the keyword match
> isn't even needed: "raise expression" could do the job, or they
> could be
> aliases to signify intent.
>
> In other words, a match expression would always "fail". The only
> mismatch here is that it points out the difference between
> try-else and
> match-else: try-else is executed if there is no failure, but if match
> always fails, else would never be appropriate, and case _: would be.
>
> In any case, it does seem there is a strong correlation between match
> processing and try processing, that I didn't see during other
> discussions of the possible structural similarities. "match 3 / 0:"
> would clearly need to be wrapped in a try:
>
> try:
>      match x / y:
>           case 43:
>                 print("wow, it is 43")
>           case 22:
>                 print("22 seemed less likely than 43 for some reason")
>          case _:
>                print("You get what you get")
> except ZeroDivisionError as exc:
>      print(f"But sometimes you get an exception {exc}")
>
> or:
>
> try:
>      raise x / y
> case 43:
>      print("wow, it is 43")
> case 22:
>      print("22 seemed less likely than 43 for some reason")
> case exc := ZeroDivisionError:
>      print(f"But sometimes you get an exception: {exc}")
> case _:
>      print("You get what you get")
> _______________________________________________
> Python-Dev mailing list -- python-dev@python.org
> <mailto:python-dev@python.org>
> To unsubscribe send an email to python-dev-leave@python.org
> <mailto: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/GDP2KKB3SUWQZRSNTR5N36LXZ6HDS2QL/
> 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 ]
Hello,

On Sat, 11 Jul 2020 00:35:39 +0200
Federico Salerno <salernof11@gmail.com> wrote:

[]

> A few emails ago I proposed something like this (and I'm probably
> only the last one to do so amongst many), but if anyone made an
> argument against it I must have missed it:

The PEP itself in "rejected" ideas makes an argument against it:
indented stuff after a line ending with ":" must be a *statement*. It
would be totally nuts for that to be something else, e.g. an expression:

>
> match:
>     a
> case 1:
>     ...
> case 2:
>     ...
> else:
>     ...

> (The a on a separate line being arguable.)

That of course leads us to the obvious idea:

match a:
case 1:
    ...
case 2:
    ...
else:
    ...


Of course, PEP smartly has an argument against that too, in the vein of
"after line ending with ':', there should be an indent suite (list of
statements)". But that's where it goes sideways. That argument is no
better than the argument "there should be no normally looking
identifiers with magic behavior", but look, very this PEP does exactly
that with the identifier "_".

And if the above snippet looks weird to anybody, it's only because of
all the "case" business. There wouldn't be such a problem if it was
instead:

match a:
| 1:
    ...
| 2:
    ...
|:
    ...

The above ML-like syntax should be perfect for almost everyone, ...
except the PEP authors, because they have it in "rejected ideas" either.


--
Best regards,
Paul mailto:pmiscml@gmail.com
_______________________________________________
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/7V7BS3ICKE5PJZD5Q2I65ALZQNXROPZU/
Code of Conduct: http://python.org/psf/codeofconduct/
Re: PEP 622 version 2 (Structural Pattern Matching) [ In reply to ]
I did make the following arguments about less indentation in
https://github.com/gvanrossum/patma/issues/59

To recap:

1. Similarity to if/elif/else and try/except/finally statements in how
code lines up
2. Less apparent complexity, since indentation is a visual signal for
such
3. Smaller, more meaningful diffs when refactoring if/elif/else chains

Just to be clear, I wanted to capture these as possible objections, I'm not
greatly in favor of one indentation scheme or the other - there are good
arguments for the indentation scheme of the current PEP (which it makes).

- Jim

On Fri, Jul 10, 2020 at 5:11 PM Paul Sokolovsky <pmiscml@gmail.com> wrote:

> Hello,
>
> On Sat, 11 Jul 2020 00:35:39 +0200
> Federico Salerno <salernof11@gmail.com> wrote:
>
> []
>
> > A few emails ago I proposed something like this (and I'm probably
> > only the last one to do so amongst many), but if anyone made an
> > argument against it I must have missed it:
>
> The PEP itself in "rejected" ideas makes an argument against it:
> indented stuff after a line ending with ":" must be a *statement*. It
> would be totally nuts for that to be something else, e.g. an expression:
>
> >
> > match:
> > a
> > case 1:
> > ...
> > case 2:
> > ...
> > else:
> > ...
>
> > (The a on a separate line being arguable.)
>
> That of course leads us to the obvious idea:
>
> match a:
> case 1:
> ...
> case 2:
> ...
> else:
> ...
>
>
> Of course, PEP smartly has an argument against that too, in the vein of
> "after line ending with ':', there should be an indent suite (list of
> statements)". But that's where it goes sideways. That argument is no
> better than the argument "there should be no normally looking
> identifiers with magic behavior", but look, very this PEP does exactly
> that with the identifier "_".
>
> And if the above snippet looks weird to anybody, it's only because of
> all the "case" business. There wouldn't be such a problem if it was
> instead:
>
> match a:
> | 1:
> ...
> | 2:
> ...
> |:
> ...
>
> The above ML-like syntax should be perfect for almost everyone, ...
> except the PEP authors, because they have it in "rejected ideas" either.
>
>
> --
> Best regards,
> Paul mailto:pmiscml@gmail.com
> _______________________________________________
> 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/7V7BS3ICKE5PJZD5Q2I65ALZQNXROPZU/
> Code of Conduct: http://python.org/psf/codeofconduct/
>
Re: PEP 622 version 2 (Structural Pattern Matching) [ In reply to ]
On 11/07/20 10:35 am, Federico Salerno wrote:
> I feel all those who aren't directly arguing against it are working off
> the assumption that it is needed for match and case to have different
> levels of indentation, but is this really true? Is there anything (bar
> tradition or other subjective arguments) that speaks in favour of this,

I can't think of one at the moment, but I don't think you
should dismiss tradition so easily. One of the arguments used
to justify significant indentation in Python is that "you're
going to indent it for readability anyway, so the compiler
might as well take notice of it".

For the most part, Python indentation follows what people
would naturally do even if they didn't have to. So I think it's
worth looking at what people typically do in other languages
that don't have mandatory indentation.

Taking C, for example, switch statements are almost always
written like this:

switch (x) {
case 1:
...
case 2:
...
default:
...
}

I've rarely if ever seen one written like this:

switch (x) {
case 1:
...
case 2:
...
default:
...
}

or like this:

switch (x) {
case 1:
...
case 2:
...
default:
...
}

This suggests to me that most people think of the cases as being
subordinate to the switch, and the default being on the same level
as the other cases.

--
Greg
_______________________________________________
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/MNDNVQTDNZDWVZ4NUTBBQQUG6K3WPKO4/
Code of Conduct: http://python.org/psf/codeofconduct/
Re: PEP 622 version 2 (Structural Pattern Matching) [ In reply to ]
Hello,

On Sat, 11 Jul 2020 22:49:09 +1200
Greg Ewing <greg.ewing@canterbury.ac.nz> wrote:

[]

> For the most part, Python indentation follows what people
> would naturally do even if they didn't have to. So I think it's
> worth looking at what people typically do in other languages
> that don't have mandatory indentation.
>
> Taking C, for example, switch statements are almost always
> written like this:
>
> switch (x) {
> case 1:
> ...
> case 2:
> ...
> default:
> ...
> }
>
> I've rarely if ever seen one written like this:
>
> switch (x) {
> case 1:
> ...
> case 2:
> ...
> default:
> ...
> }

Indeed, that's unheard of (outside of random pupil dirtcode).

Actually, the whole argument in PEP 622 regarding "else:", that its
placement is ambiguous sounds like a rather artificial write-off.
Individual "case"'s are aligned together, but suddenly, it's unclear
how to align the default case, introduced by "else"? Who in good faith
would align it with "match"?


> or like this:
>
> switch (x) {
> case 1:
> ...
> case 2:
> ...
> default:
> ...
> }

Oh really, you never saw that? Well, they say that any programmer
should eyeball the source code of the most popular open-source OS at
least once:
https://elixir.bootlin.com/linux/latest/source/kernel/sys.c#L2144

And a lot of projects follow the Linux codestyle, because it's
familiar to many people and offers ready/easy to use infrastructure for
code style control.

> This suggests to me that most people think of the cases as being
> subordinate to the switch, and the default being on the same level
> as the other cases.

And to me it suggests that well established projects, which have
thought out it all, aren't keen to use more indentation than really
needed.

> --
> Greg

[]

--
Best regards,
Paul mailto:pmiscml@gmail.com
_______________________________________________
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/YGZMM53MPLRETNBYERVI3APR7FM26EC2/
Code of Conduct: http://python.org/psf/codeofconduct/
Re: PEP 622 version 2 (Structural Pattern Matching) [ In reply to ]
On 07/11/2020 04:20 AM, Paul Sokolovsky wrote:

> Actually, the whole argument in PEP 622 regarding "else:", that its
> placement is ambiguous sounds like a rather artificial write-off.
> Individual "case"'s are aligned together, but suddenly, it's unclear
> how to align the default case, introduced by "else"? Who in good faith
> would align it with "match"?

I would.

--
~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/PF6WFVTCZOOKEERHE3YGHSUSUCFV5RZY/
Code of Conduct: http://python.org/psf/codeofconduct/
Re: PEP 622 version 2 (Structural Pattern Matching) [ In reply to ]
On Sat, 11 Jul 2020 at 14:39, Ethan Furman <ethan@stoneleaf.us> wrote:
>
> On 07/11/2020 04:20 AM, Paul Sokolovsky wrote:
>
> > Actually, the whole argument in PEP 622 regarding "else:", that its
> > placement is ambiguous sounds like a rather artificial write-off.
> > Individual "case"'s are aligned together, but suddenly, it's unclear
> > how to align the default case, introduced by "else"? Who in good faith
> > would align it with "match"?
>
> I would.

How do you feel about the fact that

match EXPR:
case 1:
print("One")
case _:
print("default")

and

match EXPR:
case 1:
print("One")
else:
print("default")

are semantically completely identical, but syntactically must be
indented differently? That for me is probably the most compelling
reason for preferring to indent else to the same level as case¹. I'm
curious to understand how people who prefer aligning else with match
view this. (Not least, because I anticipate some "interesting" code
style flamewars over this ;-))

Paul

¹ When I say "most compelling" I mean "inclines me to have a mild
preference" :-) In reality I mostly don't care, and I'll probably just
use "case _" in any projects I work on and ignore the existence of
"else" altogether.
_______________________________________________
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/ZM6CQQ4W2Q3S3NKFHPPWZHJPK3FNHJJW/
Code of Conduct: http://python.org/psf/codeofconduct/
Re: PEP 622 version 2 (Structural Pattern Matching) [ In reply to ]
To me, "else:" has a slightly different meaning than "case _:"

case _: essentially a default, ensuring that the match logic is complete.

else: OK, the subject of this match failed, here is our fallback logic.

Whether this distinction is important enough to express in code is another question, as is whether or not anyone but me would follow this "obvious" convention. So I'm not convinced the difference justifies the existence a second syntax. But I'm also not sure it doesn't, particularly if that distinction were given in the PEP and in documentation for the match statement.

-jJ
_______________________________________________
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/TLQGEZQXGU37BZFQVIY52JVNBP77T6GV/
Code of Conduct: http://python.org/psf/codeofconduct/
Re: PEP 622 version 2 (Structural Pattern Matching) [ In reply to ]
Glenn Linderman wrote:
> On 7/10/2020 3:15 AM, Gustavo Carneiro wrote:
...
> > Therefore, I posit that the style of try...except indentation only
> > works where the number of cases is small.
> > But for the case of pattern matching, I expect the number of cases to
> > be matched to be a lot higher than exception handling cases.  Having
> > cases to be matched be indented is, IMHO, a nice visual cue to help
> > the reader understand where the pattern matching block ends.

> Actually, the current  if elseif elseif elseif else, used now because
> Python has no switch/match/case, has exactly the same issue as you
> describe as a problem with try if there were more cases... and if often
> has more cases, just like match will.

True

> So your concern seems nebulous. You may have wished for extra
> indentation.... but it is simple to get more indentation: use 8 spaces
> instead of 4. So if you really wanted it, you could have had it.

Not so true.

if a: ...
elif b: ...
elif c: ...
else:

is not valid. In practice, I interpret wanting to indent at a place that doesn't require it as a code smell suggesting I should try to break out a helper function, but ... it does happen.

-jJ
_______________________________________________
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/RVMN33GUGKUUFCEEHYCNJPT7MQ7AI5IW/
Code of Conduct: http://python.org/psf/codeofconduct/
Re: PEP 622 version 2 (Structural Pattern Matching) [ In reply to ]
On 7/11/2020 10:36 AM, Jim J. Jewett wrote:
> Glenn Linderman wrote:
>> On 7/10/2020 3:15 AM, Gustavo Carneiro wrote:
> ...
>>> Therefore, I posit that the style of try...except indentation only
>>> works where the number of cases is small.
>>> But for the case of pattern matching, I expect the number of cases to
>>> be matched to be a lot higher than exception handling cases.  Having
>>> cases to be matched be indented is, IMHO, a nice visual cue to help
>>> the reader understand where the pattern matching block ends.
>> Actually, the current  if elseif elseif elseif else, used now because
>> Python has no switch/match/case, has exactly the same issue as you
>> describe as a problem with try if there were more cases... and if often
>> has more cases, just like match will.
> True
>
>> So your concern seems nebulous. You may have wished for extra
>> indentation.... but it is simple to get more indentation: use 8 spaces
>> instead of 4. So if you really wanted it, you could have had it.
> Not so true.

It is true, the way I meant it, but not the way you (mis-)interpreted it.
>
> if a: ...
> elif b: ...
> elif c: ...
> else:
>
> is not valid. In practice, I interpret wanting to indent at a place that doesn't require it as a code smell suggesting I should try to break out a helper function, but ... it does happen.

if  a:
        ...
elif b:
        ...
elif c:
        ...
else:
    ...

is perfectly valid.
_______________________________________________
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/IEZ5PTLDDGFTT6763FUH4MNXNXFNWAR2/
Code of Conduct: http://python.org/psf/codeofconduct/
Re: PEP 622 version 2 (Structural Pattern Matching) [ In reply to ]
> On 10 Jul 2020, at 18:28, Jim Baker <jim.baker@python.org> wrote:
>
> On Fri, Jul 10, 2020, 9:16 AM Eric Nieuwland <eric.nieuwland@gmail.com> wrote:
>
>> On 10 Jul 2020, at 01:51, Jim Baker <jim.baker@python.org> wrote:
>> ...
>> Explicit namespacing (if a constant) or using a guard (if a variable) seems to be the right solution, as Ethan demonstrated earlier. No need for . or ^ or \ or ... to disambiguate. Also it seems to me that structural pattern matching will build on two common usages of namespaces for constants:
>>
>> 1. Constants used from other modules are almost always used in the module namespace. Eg, socket.AF_UNIX or signal.SIGTERM.
>> 2. New code often tends to use constants defined within an Enum namespace. Hopefully we will see more of this convention in usage.
>>
>> (Very much an aside: Interestingly with the socket module we see both used - it defines its constants with IntEnum and exports them traditionally. The namespace specifics it uses with IntEnum._convert_ to make this happen -- strictly speaking EnumMeta._convert, not documented, and a bit hard to follow -- might be possibly debatable, but it works out quite well in practice in providing backwards compatibility while continuing to work with a C source of these constants.)
>>
>> This would also mean
>> case Point(x=\x, y=\y):
>> should be used to obtain x and y from the Point instance.
>
> This approach makes deeper nesting of the structure much more cumbersome, I think.
>
> How to match Polygon(Point(x0,y0), Point(x1, y1), Point(x2, y2)) based on its structure?
> And Polygon(Point(x0,y0), p1, Point(x2, y2))?
>
>
> I'm just trying to describe what v2 of the PEP is trying to do and how it then corresponds to a reasonable usage model. Sorry for any confusion.

Yes, I understood. Thank you for that. No apology needed.

> So in your scenario above, Polygon and Point are used as class patterns (https://www.python.org/dev/peps/pep-0622/#class-patterns). Consequently they are treated accordingly and have that nice structural pattern matching quality!

What I meant to say is that as I read the current PEP text there would be a confusing difference between

match poly:
case Polygon(Point(x0, y0), Point(x1, y1), Point(x2, y2)):
...

and

p0 = Point(x0, y0)
p1 = Point(x1, y1)
p2 = Point(x2, y2)
match poly:
case Polygon(p0, p1, p2):
...

This would be especially clumsy if I need to match parts in a deep structure.
It would require me to either write the whole construction as part of the ‘match’ or use ‘match’ nested to drill down to the parts I need.

> Earlier I was discussing constant patterns (https://www.python.org/dev/peps/pep-0622/#constant-value-patterns), which require they be namespaced in some way (a qualified name as it is described in the PEP).

Indeed.
My point is this would be - as far as I know - the first time you need to create a namespace to use the value of an already known variable.
This only to allow assignment to variables which I find counterintuitive and which IMHO leads to clumsy constructions, as shown above.

So I hope the new and special thing here (i.e. assign matched parts of the structure to variables) will not interfere with how we read expressions in Python.
A special indicator for the special use case to me seems far easier to understand and to teach.

—eric
_______________________________________________
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/ZXYKO57S6U5UNQG6Y5IUXIXI54RBV2QD/
Code of Conduct: http://python.org/psf/codeofconduct/
Re: PEP 622 version 2 (Structural Pattern Matching) [ In reply to ]
On 11/07/2020 00:57, Paul Sokolovsky wrote:
> The PEP itself in "rejected" ideas makes an argument against it:
> indented stuff after a line ending with ":" must be a *statement*. It
> would be totally nuts for that to be something else, e.g. an expression:
Good point.
> That of course leads us to the obvious idea:
> match a: case 1: ??? ... case 2: ??? ... else: ??? ... Of course, PEP
> smartly has an argument against that too, in the vein of "after line
> ending with ':', there should be an indent suite (list of
> statements)". But that's where it goes sideways.

Exactly. I think not identing what comes after match a: comes with far
more advantages than disadvantages. In fact, if the only "real" issue is
that anything after : must be indented, I'd say it is vastly outweighed
by the issues not doing it would solve.

Would the parser allow us to write the above without the colon, thus
avoiding the aforementioned objection?

> And if the above snippet looks weird to anybody, it's only because of
> all the "case" business. There wouldn't be such a problem if it was
> instead: match a: | 1: ??? ... | 2: ??? ... |: ??? ... The above
> ML-like syntax should be perfect for almost everyone, ... except the
> PEP authors, because they have it in "rejected ideas" either.

I don't know, that doesn't look very pythonic based on the preference
Python makes for words over symbols. I don't think there's any problem
with using case, it's the expectations many have for what should come
around it that creates issues.

On 11/07/2020 12:49, Greg Ewing wrote:
> I can't think of one at the moment, but I don't think you
> should dismiss tradition so easily.

I don't mean to dismiss it, but I wouldn't want it to get in the way of
a change if there are good reasons to go against tradition. This seems
like one of these cases to me.

> One of the arguments used
> to justify significant indentation in Python is that "you're
> going to indent it for readability anyway, so the compiler
> might as well take notice of it".
>
> For the most part, Python indentation follows what people
> would naturally do even if they didn't have to. So I think it's
> worth looking at what people typically do in other languages
> that don't have mandatory indentation.
>
> [...]
>
> or like this:
>
> ?? switch (x) {
> ?? case 1:
> ????? ...
> ?? case 2:
> ????? ...
> ?? default:
> ????? ...
> ?? }
>
> This suggests to me that most people think of the cases as being
> subordinate to the switch, and the default being on the same level
> as the other cases.

I think that last one would be perceived as ok if it weren't for the
brackets: everyone naturally indents any set of brackets' contents. I
wouldn't normally mind cases being indented extra relative to "match" if
not for two points:

1. Python relies heavily on indentation. It's likely for a match block
to appear in a place that is already well indented, *and* it is also
likely to often include further levels of indentation. It would be
preferable not to require two levels at a minimum every time a match
block is needed.

2. Unless the default case is signalled with an ad-hoc keyword like
default (which I personally would like), it seems a wildcard symbol like
the controversial _ is needed to pair with case. Going against tradition
and setting only one indentation level would solve this issue, while
still allowing (I think) any programmer to indent the default case extra
if they so wish.

If none of this is convincing, I do believe the matter is easier than it
appears, because few would be confused by else being at the same level
as each other case.

Alternatively, what if (gasp!) both were allowed as synonyms? I'm sure
one of the two would eventually settle as conventional, and there is no
possible ambiguity. I know it goes against the "one obvious way to do
it" precept but it's clear that there is no obvious way here at all, so,
?porque no los dos?

1 2 3 4 5 6 7  View All