[Python-Dev] Re: PEP 622 version 2 (Structural Pattern Matching)

2020-07-12 Thread Larry Hastings


On 7/8/20 8:02 AM, Guido van Rossum wrote:

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.



In that case, I'd like to make a specific pitch for "don't make '_' 
special".  (I'm going to spell it '_' as it seems to be easier to read 
this way; ignore the quotes.)



IIUC '_' is special in two ways:

1) we permit it to be used more than once in a single pattern, and
2) if it matches, it isn't bound.

If we forego these two exceptions, '_' can go back to behaving like any 
other identifier.  It becomes an idiom rather than a special case.



Drilling down on what we'd need to change:

To address 1), allow using a name multiple times in a single pattern.

622 v2 already says:

   For the moment, we decided to make repeated use of names within the
   same pattern an error; we can always relax this restriction later
   without affecting backwards compatibility.

If we relax it now, then we don't need '_' to be special in this way.  
All in all this part seems surprisingly uncontentious.



To address 2), bind '_' when it's used as a name in a pattern.

This adds an extra reference and an extra store.  That by itself seems 
harmless.


The existing implementation has optimizations here.  If that's 
important, we could achieve the same result with a little dataflow 
analysis to optimize away the dead store.  We could even special-case 
optimizing away dead stores /only/ to '_' and /only/ in match/case 
statements and all would be forgiven.


Folks point out that I18N code frequently uses a global function named 
'_'.  The collision of these two uses is unfortunate, but I think it's 
survivable.  I certainly don't think this collision means we should 
special-case this one identifier in this one context in the /language/ 
specification.


Consider:

 * There's no installed base of I18N code using pattern matching,
   because it's a new (proposed!) syntax.  Therefore, any I18N code
   that wants to use match/case statements will be new code, and so can
   be written with this (admittedly likely!) collision in mind.  I18N
   code could address this in several ways, for example:
 o Mandate use of an alternate name for "don't care" match patterns
   in I18N code, perhaps '__' (two underscores).  This approach
   seems best.
 o Use a different name for the '_' function in scopes where you're
   using match/case, e.g. 'gettext'.
 o Since most Python code lives inside functions, I18N code could
   use '_' in its match/case statements, then "del _" after the
   match statement.  '_' would revert back to finding the global
   function.  (This wouldn't work for code at module scope for
   obvious reasons.  One /could/ simply rebind '_', but I doubt
   people want to consider this approach in the first place.)
 * As the PEP mentions, '_' is already a Python idiom for "I don't care
   about this value", e.g. "basename, _, extension =
   filename.partition('.')".  I18N has already survived contact with
   this idiom.
 * Similarly, '_' has a special meaning in the Python REPL. Admittedly,
   folks don't use a lot of I18N work in the REPL, so this isn't a
   problem in practice.  I'm just re-making the previous point: I18N
   programmers already cope with other idiomatic uses of '_'.
 * Static code analyzers could detect if users run afoul of this
   collision.  "Warning: match/case using _ in module using _ for
   gettext" etc.


One consideration: if you /do/ use '_' multiple times in a single 
pattern, and you /do/ refer to its value afterwards, what value should 
it get?  Consider that Python already permits multiple assignments in a 
single expression:


   (x:="first", x:="middle", x:="last")

After this expression is evaluated, x has been bound to the value 
"last".  I could live with "it keeps the rightmost".  I could also live 
with "the result is implementation-defined".  I suspect it doesn't 
matter much, because the point of the idiom is that people don't care 
about the value.



In keeping with this change, I additionally propose removing '*_' as a 
special token.  '*_' would behave like any other '*identifier', binding 
the value to the unpacked sequence. Alternately, we could keep the 
special token but change it to '*' so it mirrors Python function 
declaration syntax.  I don't have a strong opinion about this second 
alternative.



Cheers,


//arry/

___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/OF4BT5HEWPEGDHNPX26NCANJBYQLLCHT/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: Python-Dev Digest, Vol 204, Issue 75

2020-07-12 Thread Federico Salerno

On 11/07/2020 19:29, Jim J. Jewett wrote:
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


Could you construct two examples to prove behaviour would be different 
between the two? To me the two meanings seem too similar to make a 
difference in code.


On 12/07/2020 00:31, Guido van Rossum wrote:

Hm... Just the fact that people have been arguing both sides so 
convincingly makes me worry that something bigger is amiss. I think 
we're either better off without `else` (since the indentation of `case 
_` cannot be disputed :-), or we have to revisit the reasons for 
indenting `case` relative to `match`. As MRAB said, it's a case of 
picking the least inelegant one.


Let me add that the parser can easily deal with whatever we pick -- 
this is purely about human factors.
That is a good point. I don't think there would be any particular 
objection to allowing one case to catch anything that wasn't caught 
before—the issue is with making _ (or any other particular symbol) 
special for the occasion, or at the very least none of those proposed 
thus far has been universally accepted.


Was anything beside _ and ... proposed? What if case object(): or case 
any: did that instead? The former is already used to a similar meaning 
in the context of a match block, the latter would be very obvious to any 
reader and, since it's already a builtin, few would think shadowing it 
for use as a store-identifier would be a good idea.


On 11/07/2020 21:13, Eric Nieuwland wrote:
This could also resolve the discussion on indentation of the ‘case’ 
parts and the placement of the default matching:
match  [as ]:  case  
[]:  … [else: ] within the preparation 
statements it would then be allowed to use undefined variables as 
receivers of matched parts.


This is intriguing, but I do share Greg Ewing's doubt: what happens if 
you need no preparation? Personally I'd accept if the line could be 
omitted altogether, but I understand many others are opposed to having 
the line following a colon be indented at the same level, and likewise I 
don't think the idea of having to write pass (or ...) explicitly when no 
preparation is needed will be well received.


___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/MMDXSHHLM6CI3S6TFTCI3VLES3N2RLAS/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 622 version 2 (Structural Pattern Matching)

2020-07-12 Thread Federico Salerno

On 12/07/2020 11:38, Larry Hastings wrote:
In that case, I'd like to make a specific pitch for "don't make '_' 
special".  (I'm going to spell it '_' as it seems to be easier to read 
this way; ignore the quotes.)


IIUC '_' is special in two ways:

1) we permit it to be used more than once in a single pattern, and
2) if it matches, it isn't bound.

If we forego these two exceptions, '_' can go back to behaving like 
any other identifier.  It becomes an idiom rather than a special case.


Drilling down on what we'd need to change:

To address 1), allow using a name multiple times in a single pattern.

622 v2 already says: [...]

If we relax it now, then we don't need '_' to be special in this way.  
All in all this part seems surprisingly uncontentious.


To address 2), bind '_' when it's used as a name in a pattern.

This adds an extra reference and an extra store.  That by itself seems 
harmless.


The existing implementation has optimizations here.  If that's 
important, we could achieve the same result with a little dataflow 
analysis to optimize away the dead store.  We could even special-case 
optimizing away dead stores /only/ to '_' and /only/ in match/case 
statements and all would be forgiven.


Folks point out that I18N code frequently uses a global function named 
'_'.  The collision of these two uses is unfortunate, but I think it's 
survivable.  I certainly don't think this collision means we should 
special-case this one identifier in this one context in the /language/ 
specification.


Consider:

  * There's no installed base of I18N code using pattern matching,
because it's a new (proposed!) syntax.  Therefore, any I18N code
that wants to use match/case statements will be new code, and so
can be written with this (admittedly likely!) collision in mind.
I18N code could address this in several ways, for example:
  o Mandate use of an alternate name for "don't care" match
patterns in I18N code, perhaps '__' (two underscores).  This
approach seems best.

In keeping with this change, I additionally propose removing '*_' as a 
special token.  '*_' would behave like any other '*identifier', 
binding the value to the unpacked sequence.  Alternately, we could 
keep the special token but change it to '*' so it mirrors Python 
function declaration syntax.  I don't have a strong opinion about this 
second alternative.


+1 to everything

One consideration: if you /do/ use '_' multiple times in a single 
pattern, and you /do/ refer to its value afterwards, what value should 
it get? Consider that Python already permits multiple assignments in a 
single expression:


(x:="first", x:="middle", x:="last")

After this expression is evaluated, x has been bound to the value 
"last".  I could live with "it keeps the rightmost".  I could also 
live with "the result is implementation-defined".  I suspect it 
doesn't matter much, because the point of the idiom is that people 
don't care about the value.


I'd expect it to bind to the last one. If that's in any way problematic, 
in order to prevent oblivious misuse, referencing an identifier that was 
bound more than once should raise an exception. But as you say, it 
doesn't really matter.


___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/ZKW6AOZIYPTCTIQLFZ6L37JXTZKTAYVM/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 622 version 2 (Structural Pattern Matching)

2020-07-12 Thread Rhodri James

On 11/07/2020 20:13, Eric Nieuwland wrote:

Just after I hit ‘send’ it dawned on me it might be preferable to make that

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

so the part preceded by ‘match’ is the preparation phase for matching.


Are you intending p0, p1 and p2 to be subpatterns rather than object 
instantiations?  That makes me a little twitchy; the difference between 
what you wrote and:


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

is very easy to miss.

--
Rhodri James *-* Kynesim Ltd
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/VOKSUVYJTFKTES6Z7SSEZAVKOW6FT4UQ/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 622 version 2 (Structural Pattern Matching)

2020-07-12 Thread Rhodri James

On 11/07/2020 12:20, 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, if I'd used an "else" with a "for" recently.  I would have a 
strong tendency to align the "else" with the "case" statements, but I 
can see how the other way around makes sense too.


(I can't see how anyone likes the Linux case indentation style at all. 
It's horrible to read.)


--
Rhodri James *-* Kynesim Ltd
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/YAAEFSSIT3QL2AZJCUP6UZZTU7AYLVEF/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 622 version 2 (Structural Pattern Matching)

2020-07-12 Thread Paul Moore
On Sun, 12 Jul 2020 at 10:47, Larry Hastings  wrote:
> In that case, I'd like to make a specific pitch for "don't make '_' special". 
>  (I'm going to spell it '_' as it seems to be easier to read this way; ignore 
> the quotes.)

Overall, this sounds mostly reasonable. I'm cutting nearly everything
here, because I don't have anything to add.

> One consideration: if you do use '_' multiple times in a single pattern, and 
> you do refer to its value afterwards, what value should it get?  Consider 
> that Python already permits multiple assignments in a single expression:
>
> (x:="first", x:="middle", x:="last")
>
> After this expression is evaluated, x has been bound to the value "last".  I 
> could live with "it keeps the rightmost".  I could also live with "the result 
> is implementation-defined".  I suspect it doesn't matter much, because the 
> point of the idiom is that people don't care about the value.

The problem for me is specifically with variables *other* than `_` -
precisely because `_` has connotations of "don't care".

If I see

match expr:
case Point(x, x):
# what is x here?

I would very strongly expect that to mean that the two components of
Point were equal, and x was set to the common value. That's not what
Python does, so this would be a fairly easy mistake to make.

For what it's worth, it looks like Rust uses the same rule as the PEP
- multiple occurrences of the same variable are not allowed, but _ is
a wildcard that *can* be used multiple times, but isn't bound.
Paul
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/EC6MQQ6BKU6Y2KN5R6V2CEWJQ5I3NQO6/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: Python-Dev Digest, Vol 204, Issue 75

2020-07-12 Thread Larry Hastings

On 7/12/20 2:38 AM, Federico Salerno wrote:

Was anything beside _ and ... proposed?



Yes, the PEP mentions using '?'.  It isn't the authors' first choice but 
it seems they're not dead-set against it either. Personally I prefer it 
to special-casing '_'.  It has no meaning in Python syntax yet, it would 
clearly not be an identifier (so no one would be surprised that it 
doesn't bind), and it's inspired by shell globbing.  '*' already means 
"match more than one thing" in several places, including PEP 622, and 
I'm guessing was also inspired by shell globbing, so there's some mild 
precedence to borrowing that syntax.



//arry/

___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/XUF6ENRMNJ5K2DZ6UUXP27VEBEJX2F4F/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 622 version 2 (Structural Pattern Matching)

2020-07-12 Thread Daniel Moisset
Hey Larry, just to clarify on a single point you make:

On Sun, 12 Jul 2020 at 10:48, Larry Hastings  wrote:

> [ snip ]
> To address 2), bind '_' when it's used as a name in a pattern.
>
> This adds an extra reference and an extra store.  That by itself seems
> harmless.
>

This is not always just a store. for patterns like `[a, *_, b]` vs `[a,
*ignore_me, b]`, the current semantics mean that the matching process has
to make 2 calls to `__getitem__` on the match subject. The second case
(which would be equivalent to "remove special meaning on _") will have to
actually create a new list and copy most of the original one which can be
arbitrarily long, so this turns an O(1) operation into O(n).

> The existing implementation has optimizations here.  If that's important,
> we could achieve the same result with a little dataflow analysis to
> optimize away the dead store.  We could even special-case optimizing away
> dead stores *only* to '_' and *only* in match/case statements and all
> would be forgiven.
>
This might work, although it's quite different to what python does in
general (are you supposed to see the value of `_` in a debugger? or in
`locals()`?  )

Cheers,
D.
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/ROHP3JPDJPFYIOL2ILUAZRL7JHW46NHW/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: Python-Dev Digest, Vol 204, Issue 75

2020-07-12 Thread Jim J. Jewett
Federico Salerno wrote:
> On 11/07/2020 19:29, Jim J. Jewett wrote:
> > To me, "else:" has a slightly different meaning than "case _:" ...

> Could you construct two examples to prove behaviour would be different 
> between the two? 

The behavior would be identical; the difference is in why I put that
behavior there.

match return_code:
case -1: ...
case 4: ...
case x if int(x) == x:
pass # This could be a "case _" if not for the guard
else:
raise TypeError("Return Code not an integer?!?: ", return_code)
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/PGML33TN7ZHNLS7VPRQA3CTRAANOTXRF/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 622 version 2 (Structural Pattern Matching)

2020-07-12 Thread Eric Nieuwland
Greg Ewing wrote:
> Eric Nieuwland wrote:
> 
>> ...
>> match poly:
>>   p0 = Point(x0, y0)
>>   p1 = Point(x1, y1)
>>   p2 = Point(x2, y2)
>>   case Polygon(p0, p1, p2):
>>   …
>> 
> 
> Interesting idea, but what happens if you don't
>  need any setup?
> Do you have to write
> 
> 
>  match poly:
>  pass
>  case ...
> 
> ?

Yes, that would be the idea.

Unless you would need to setup variables to be bound in the cases, of course.
Without that an if … elif … elif … else structure would be equivalent and 
possibly preferable.
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/CMDHKH3YPLIQ4WGI4MEL2BQKKVU6DGDE/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: Python-Dev Digest, Vol 204, Issue 75

2020-07-12 Thread Jonathan Goble
On Sun, Jul 12, 2020 at 1:16 PM Jim J. Jewett  wrote:

> Federico Salerno wrote:
> > On 11/07/2020 19:29, Jim J. Jewett wrote:
> > > To me, "else:" has a slightly different meaning than "case _:" ...
>
> > Could you construct two examples to prove behaviour would be different
> > between the two?
>
> The behavior would be identical; the difference is in why I put that
> behavior there.
>
> match return_code:
> case -1: ...
> case 4: ...
> case x if int(x) == x:
> pass # This could be a "case _" if not for the guard
> else:
> raise TypeError("Return Code not an integer?!?: ", return_code)
>

I would write that as:

match return_code:
case -1: ...
case 4: ...
case x if int(x) != x:
raise TypeError("Return Code not an integer?!?: ", return_code)
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/UPR3ZPYK5U4E5WO5BL4DBSZG52WWMG4D/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 622 version 2 (Structural Pattern Matching)

2020-07-12 Thread Eric Nieuwland
Rhodri James wrote:

> Eric Nieuwland wrote:
> 
>> Just after I hit ‘send’ it dawned on me it might be preferable to make that
>> 
>> match poly:
>>  p0 = Point(x0, y0)
>>  p1 = Point(x1, y1)
>>  p2 = Point(x2, y2)
>> case Polygon(p0, p1, p2):
>>  …
>> 
>> so the part preceded by ‘match’ is the preparation phase for matching.
>> 
> Are you intending p0, p1 and p2 to be subpatterns rather than object 
> instantiations? That makes me a little twitchy; the difference between what 
> you wrote and:
> 
> match poly:
>   p0 = Point(x0, y0)
>   p1 = Point(x1, y1)
> case Polygon(p0, p1, p2):
>   ... 
> is very easy to miss.
> 

You are perfectly right.
That is why I prefer explicit marking of variables to be bound by matching.
Your example could then become:

match poly:
p0 = Point(x0, \y0)
p1 = Point(\x1, y1)
case Polygon(p0, p1, \p2):
… 

and IMHO it would be very clear what to expect.

An alternative would be to ‘declare’ variables that are to be bound to make 
things even more explicit, like:

match poly:
x1 = to_be_bound_by_matching
y0 = to_be_bound_by_matching
p2 = to_be_bound_by_matching
p0 = Point(x0, y0)
p1 = Point(x1, y1)
case Polygon(p0, p1, p2):
… 

where a better name than ‘to_be_bound_by_matching’ would certainly be needed.

—eric
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/W6VILFGBO4HJLEAUTSW6SJMNZN352KTJ/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 622 version 2 (Structural Pattern Matching)

2020-07-12 Thread Larry Hastings

On 7/12/20 9:04 AM, Daniel Moisset wrote:


The existing implementation has optimizations here.  If that's
important, we could achieve the same result with a little dataflow
analysis to optimize away the dead store.  We could even
special-case optimizing away dead stores /only/ to '_' and /only/
in match/case statements and all would be forgiven.

This might work, although it's quite different to what python does in 
general (are you supposed to see the value of `_` in a debugger? or in 
`locals()`?  )



All excellent points.  The debugger question is easier to answer.  
Debuggers for compiled code have dealt with this for years; I'm unsure 
of the exact wording but gdb prints something like "".


As for locals(), my first thought was "suppress the optimization in the 
presence of a locals() call".  I dimly recall a precedent where the 
presence of locals() in a function body affected code generation, though 
sadly it escapes me at the moment**.  Anyway, that seems like a nasty 
hack, and it only handles one method of extracting a locals 
dict--there's several more, including sys._getframe and 
inspect.getframeinfo.  And then the user could rebind those and we 
wouldn't notice.  This seems like a non-starter.


Having thought about it some, I propose it'd be acceptable to do dead 
store optimization if-and-only-if optimizations are explicitly enabled, 
e.g. with "-O".  Allowing explicitly-enabled optimizations to observably 
affect runtime behavior does have some precedent, e.g. "-OO" which 
breaks doctest, docopt, etc.  It'd be a shame if the existence of 
locals() et al meant Python could never ever perform dead store 
optimization.



Your other (elided) point is correct too, about sequence matching for a 
sequence we don't care about not being as cheap and simple as a store 
and an extra reference.



Cheers,


//arry/

** Or maybe I'm confused and thinking of something else entirely.  Maybe 
it was "import * inside a function body disables fast locals in Python 
2"?  But that doesn't seem to be true either.


___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/G3DZWKV4MAGWHF3B3VI3RLGVPW3ALCRT/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 622 version 2 (Structural Pattern Matching)

2020-07-12 Thread Eric V. Smith

On 7/11/2020 7:54 PM, Greg Ewing wrote:


I can see that being a reasonable choice if you're using 8-space
indents, but I don't see that done much in Python.

Also, directly translating this into Python leads to something that
looks like a mistake:

    match x:
    case 1:
    ...
    case 2:
    ...

and as has been pointed out, the alternative of putting x on the
next line is unprecedented in Python.


If the 2 levels of indenting are really offensive, surely we could teach 
editors, black, ourselves, etc. to indent the match statement as:


match pt:
  case (x, y):    # <-- indent by two spaces
    return Point3d(x, y, 0)   # <-- indent by 2 more spaces, for a 
total of 4


if x:
    return x  # <-- normally indent by 4 spaces

I used to do something similar with C switch statements.

I guess you couldn't use this trick if you were using tabs. Another 
reason to not use them!


Eric

___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/MZWH24XT5PDP3THWC6LL6Q4ITAASAKON/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 622 version 2 (Structural Pattern Matching)

2020-07-12 Thread Barry Warsaw
On Jul 11, 2020, at 13:28, MRAB  wrote:

> Another possibility is:
> 
>match:
>...
>case ...:
>case ...:

It’s ugly, but you could introduce and require a (soft) keyword on the line 
after match, e.g.

match:
# Can’t really use `with` here although I think it reads better.
as expression
case …

I still wish cases lined up under match, but it’s not a deal breaker for me.

-Barry



signature.asc
Description: Message signed with OpenPGP
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/URHMBBJ472EB6PCAH6LPM5PCBPMCHGMO/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 622 version 2 (Structural Pattern Matching)

2020-07-12 Thread Ethan Furman

On 07/11/2020 03:31 PM, Guido van Rossum wrote:

On Sat, Jul 11, 2020 at 2:45 PM Ethan Furman wrote:

On 07/11/2020 10:29 AM, Jim J. Jewett wrote:



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.


This is exactly how I would use it.


Hm... Just the fact that people have been arguing both sides so convincingly 
makes me worry that something bigger is amiss.


I think it just means there are several "right" ways to do it, we just need to 
pick one.  I'll be happy to use whatever we end up with*.

--
~Ethan~


* I hope.  ;-)
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/TJFM23YDMTMIKMQL74P3FHFGD3H5JM3T/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] PEP 622 and fitting the pieces together

2020-07-12 Thread Paul Svensson



Having followed this discussion for a while, I'm trying to put my finger on
why I feal uneasy about it.

The major features I see in this proposal are:
   * New syntax for trying multiple assignments until one matches.
   * Extending destructuring assignment to match constants in the LHS.
   * Adding syntax to tell constants from targets.
   * Extending destructuring assignment to match isinstance and properties.
   * Making _ a special variable that doesn't always gets assigned a value.

I see the other features are only discussed as part of the first one.
I think each feature has (some) value on its own, could be implemented
without the others, so really should stand or fall on it's own merit.

And there I found the root of my uneasiness - the supporting cast is stronger
than the main actor.  To me, that suggest we should change focus, to look at
the usefulness of these extensions in themselves, relegating the match/case
statement to syntactic sugar.

 /Paul
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/UG4IHD4O2X2STD2L3YAHZRI4YH7YLA5Z/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 622 version 2 (Structural Pattern Matching)

2020-07-12 Thread Guido van Rossum
On Sun, Jul 12, 2020 at 12:12 PM Larry Hastings  wrote:

> Having thought about it some, I propose it'd be acceptable to do dead
> store optimization if-and-only-if optimizations are explicitly enabled,
> e.g. with "-O".  Allowing explicitly-enabled optimizations to observably
> affect runtime behavior does have some precedent, e.g. "-OO" which breaks
> doctest, docopt, etc.  It'd be a shame if the existence of locals() et al
> meant Python could never ever perform dead store optimization.
>

Assuming you're still talking about how to implement wildcards, it really
sounds like you're willing to add a lot of complexity just to have a
"consistent" treatment of `_`. But why would you care so much about that
consistency? When I write `for x, _, _ in pts` the main point is not that I
can write `print(_)` and get the z coordinate. The main point is that I am
not interested in the y or the z coordinates (and showing this to the
reader up front). The value assigned to `_` is uninteresting (even in a
debug session, unless you're debugging Python itself).

Using the same character in patterns makes intuitive sense to anyone who is
familiar with this convention in Python. Furthermore it also makes sense to
anyone who is familiar with patterns in other languages: *all* languages
with structural pattern matching that we found at uses `_` -- C#, Elixir,
Erlang, Scala, Rust, F#, Haskell, Mathematica, OCaml, Ruby, and Swift.
(That's a much stronger precedent than the use of `?` in shell and regular
expressions IMO. :-)

The need for a wildcard pattern has already been explained -- we really
want to disallow `Point(x, y, y)` but we really need to allow `Point(z, _,
_)`. Generating code to assign the value to `_` seems odd given the clear
intent to *ignore* the value.

Using `?` as the wildcard has mostly disadvantages: it requires changes to
the tokenizer, it could conflict with other future uses of `?` (it's been
proposed for type annotations as a shorter version of Optional, and there's
PEP 505, which I think isn't quite dead yet), and Python users have no
pre-existing intuition for its meaning.

A note about i18n: it would be unfortunate if we had to teach users they
couldn't use `_` as a wildcard in patterns in code that also uses `_` as
part of the i18n stack (`from gettext import gettext as _` -- see gettext
stdlib docs). This is a known limitation on the `for x, _, _ in ...` idiom,
which I've seen people work around by writing things like `for x, __, __ in
...`. But for patterns (because the pattern code generation needs to know
about wildcards) we can't easily use that workaround. However, the solution
of never assigning to `_` (by definition, rather than through dead store
optimization) solves this case as well.

So can we please lay this one to rest?

-- 
--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-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/K5OR4QNSF2VVHJ43QTQ2AJXMLHHVA7HE/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 622 version 2 (Structural Pattern Matching)

2020-07-12 Thread MRAB

On 2020-07-12 23:20, Guido van Rossum wrote:
[snip]
The need for a wildcard pattern has already been explained -- we really 
want to disallow `Point(x, y, y)` but we really need to allow `Point(z, 
_, _)`. Generating code to assign the value to `_` seems odd given the 
clear intent to *ignore* the value.


Using `?` as the wildcard has mostly disadvantages: it requires changes 
to the tokenizer, it could conflict with other future uses of `?` (it's 
been proposed for type annotations as a shorter version of Optional, and 
there's PEP 505, which I think isn't quite dead yet), and Python users 
have no pre-existing intuition for its meaning.


FWIW, I don't think this use of '?' would conflict with the other 
suggested uses because this use would be initial in an expression, 
whereas the other uses would be non-initial.


[snip]
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/D33YT2KBNVZS27JJIYA5BDWPIP5IWB7M/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 622 version 2 (Structural Pattern Matching)

2020-07-12 Thread Terry Reedy

On 7/11/2020 6:31 PM, Guido van Rossum wrote:

Hm... Just the fact that people have been arguing both sides so 
convincingly makes me worry that something bigger is amiss. I think 
we're either better off without `else` (since the indentation of `case 
_` cannot be disputed :-), or we have to revisit the reasons for 
indenting `case` relative to `match`. As MRAB said, it's a case of 
picking the least inelegant one.


The more I think about adjusting IDLE's smart indenter to indent case 
suites once, with 2 half size indents, the more I would prefer to 
special case 'match' to have no indent (if there were no suite allowed) 
than special case 'match' and 'case' to indent 1/2 Indent.


Problem 1. Indent increments can be set to an odd number of spaces! 
(.rst files use 3 space indents.)


Problem 2. Dedent (with Backspace) could no longer be the simple 
expression I expect it currently is, such as new-indent = current-indent 
spaces // current indent size.
IDLE would have to search backwards to find the appropriate header line, 
which might not be the most recent one.  A stack of indent (delta,size) 
pairs would have to be recalculated from the most recent non-indented 
compound header line when the cursor is moved around.


Note that current indent may not be an indent size multiple number due 
to PEP8 vertical alignments, such as with function parameters or arguments.3


if a:
def fg(param1,  # comment
   param2, # 11 space indent
   | # Backspace moves cursor left 3 spaces.

The flexibility of the peg parser needs to be used with care because it 
can allow constructs that are difficult for people and non-peg code to 
read and process.


--
Terry Jan Reedy
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/SSP5EZIPOK74S26HF2GJZI4WJG7VJONZ/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 622 version 2 (Structural Pattern Matching)

2020-07-12 Thread Greg Ewing

On 13/07/20 7:12 am, Larry Hastings wrote:
I dimly recall a precedent where the 
presence of locals() in a function body affected code generation,


The presence of exec used to do that, which is why it was a
statement rather than a function. But I don't think locals()
ever did -- how would the compiler know that it was calling
the builtin locals function and not something else?

--
Greg
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/JCMENW5LTSWB62NPEDEYQK36J3ANJRGI/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 622 version 2 (Structural Pattern Matching)

2020-07-12 Thread Devin Jeanpierre
On Sun, Jul 12, 2020 at 7:36 PM Greg Ewing 
wrote:

> On 13/07/20 7:12 am, Larry Hastings wrote:
> > I dimly recall a precedent where the
> > presence of locals() in a function body affected code generation,
>
> The presence of exec used to do that, which is why it was a
> statement rather than a function. But I don't think locals()
> ever did -- how would the compiler know that it was calling
> the builtin locals function and not something else?
>

super() does something similar:

 >>> class A:
...   def super_locals(self):
... super
... return locals()
...   def superless_locals(self):
... return locals()
...
>>> A().super_locals()
{'self': <__main__.A object at 0x01FF53BCE6D8>, '__class__': }
>>> A().superless_locals()
{'self': <__main__.A object at 0x01FF53BCE7B8>}

The compiler changes what local variables exist if there is a read from a
variable named 'super', in order to support zero-argument super() calls. It
presumably could do the same sort of thing for locals(). I don't think this
is a good idea, since locals() is a debugging tool, and changing reality
based on the presence of debugging calls may make life more difficult for
the user.

-- Devin
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/QSP3RISE5HTLIUMLDMHTN7B7EEXPVVRP/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 622 version 2 (Structural Pattern Matching)

2020-07-12 Thread Greg Ewing

On 13/07/20 3:28 pm, Devin Jeanpierre wrote:
The compiler changes what local variables exist if there is a read from 
a variable named 'super',


That's fairly harmless if there's a false positive. But
accidentally getting all your locals de-optimised would be
annoying.

--
Greg
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/WPN7TNWEONPAEVDWG7J7FHFNOYQUSD2B/
Code of Conduct: http://python.org/psf/codeofconduct/