PEP 642 v2: Explicit constraint patterns *without* question marks in the syntax
Hi folks, I have updated PEP 642 significantly based on the feedback received over the past week. Since the Discourse thread hadn't received any comments on it, I amended the existing thread in place rather than making a new one: https://discuss.python.org/t/pep-642-constraint-pattern-syntax-for-structura... The full text of the PEP is quoted in the Discourse thread. The rendered version of the updated PEP can be found in the usual place: https://www.python.org/dev/peps/pep-0642/ Relative to the initially published version, the major changes are based primarily on the counterproposal that Steven D'Aprano posted: * Explicit equality constraints become "== EXPR" (replacing v1's "?EXPR") * Explicit identity constraints become "is EXPR" (replacing v1's "?is EXPR") * Inferred constraints are introduced to deal with the resulting verbosity problems. These mostly follow the same syntax as PEP 634 proposes for value patterns and literal patterns, but are defined in terms of the explicit constraints, rather than being the only way to request the desired semantics. While I considered ceding the point on using `_` as the wildcard marker (and had updated the PEP to say that), I couldn't bring myself to actually do it, especially after reading Thomas Wouters review of the current state of the pattern matching proposals. So instead this version proposes the use of `__` in that role, with an explanation of how that opens a path towards restoring language self-consistency in a future PEP by making `__` special everywhere, rather than only having it be special in match patterns. There are a few other changes that get down into the weeds of actually implementing these features in the compiler (like introducing a SkippedBinding node into the AST so most of the compiler doesn't need to care how the wildcard is spelled in the surface syntax), but I doubt those are going to matter to most folks in deciding which of the proposals on offer they prefer (or if they'd prefer continue without any pattern matching syntax at all). Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia
Hi, Le 08/11/2020 à 07:47, Nick Coghlan a écrit :
Hi folks,
I have updated PEP 642 significantly based on the feedback received over the past week.
[...] a change that I feel is insufficiently discussed is the choice to have "attr_constraint" as an inferred constraint. I can think of arguments to defer it for now at least:
* it is a one way door (if dotted names are made a constraint pattern now, they can't become a capture pattern later); * it makes a difference from assignment target syntax, where you can assign to a dotted name; * the shorthand notation is less valuable than for literals, as dotted names are verbose already, 3 more characters make little difference; * the user has no explicit syntax to override the inferred semantics. I feel like some discussion of this choice in the PEP would make sense. Cheers, Baptiste
The position of PEP 622/634/535/636 authors is clear: we see this as a necessary feature to support using enums (e.g. Color.RED) or constants defined in other modules (e.g. re.I) when simple switch functionality is being migrated from literals (e.g. case 404) to named constants (e.g. case HTTPStatus.NOT_FOUND). Bothering users with the technicality of needing to use '==' here is a big usability hit. On Thu, Nov 12, 2020 at 7:38 AM Baptiste Carvello < devel2020@baptiste-carvello.net> wrote:
Hi,
Le 08/11/2020 à 07:47, Nick Coghlan a écrit :
Hi folks,
I have updated PEP 642 significantly based on the feedback received over the past week.
[...] a change that I feel is insufficiently discussed is the choice to have "attr_constraint" as an inferred constraint. I can think of arguments to defer it for now at least:
* it is a one way door (if dotted names are made a constraint pattern now, they can't become a capture pattern later);
* it makes a difference from assignment target syntax, where you can assign to a dotted name;
* the shorthand notation is less valuable than for literals, as dotted names are verbose already, 3 more characters make little difference;
* the user has no explicit syntax to override the inferred semantics.
I feel like some discussion of this choice in the PEP would make sense.
Cheers, Baptiste _______________________________________________ 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/RQPUV7PA... Code of Conduct: http://python.org/psf/codeofconduct/
-- --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-c...>
Hello, On Thu, 12 Nov 2020 09:55:10 -0800 Guido van Rossum <guido@python.org> wrote:
The position of PEP 622/634/535/636 authors is clear: we see this as a necessary feature to support using enums (e.g. Color.RED) or constants defined in other modules (e.g. re.I) when simple switch functionality is being migrated from literals (e.g. case 404) to named constants (e.g. case HTTPStatus.NOT_FOUND). Bothering users with the technicality of needing to use '==' here is a big usability hit.
As was pointed out many times on the mailing list, there's a very obvious way around needing to use '==' there. It's explicitly marking capturing terms in case's: match foo: case ("foo", >val1): ... case ("bar", >val2): ... Besides solving the chore of needing "==" prefix, it allows for the following benefits: 1. Much more intuitive for beginners. (If Python adopts it, I see other "user-friendly" languages adopting the same pattern in the coming decades). 2. Upholds the rights of people who see "match" as glorified "switch" statement, and not keen on it doing assignments behind their backs. (The topic which was recently mentioned on the list.) 3. Solves discrepancy with cases like: # Why is this possible? obj.foo, obj.bar = val # And this is not? match val: case obj.foo, obj.bar: 4. Most uses of pattern matching known to people ("mental background") are from languages with strong culture of immutability. And that's why those languages manage to do it without much of sigils. For a language with a looming conceptual debt of not having constness/immutability in the core language semantics (aka, "Please move this subtopic to a subject that doesn’t have “PEP 622” in its topic." "https://mail.python.org/archives/list/python-dev@python.org/message/GFMOZ6XF... ), the idea to mark capturing terms, seems like a very smart way to route around this conceptual deficiency, yet improve readability. pp.3 and 4 also explain why it's obj.foo, obj.bar = val but would be: match val: case >obj.foo, >obj.bar: With destructuring assignment, the *assignment* operator is right there, and terms are on the left side of it, so it's all clear to a reader. With "match", there's no obvious assignment operator, and terms can be also used as values, so adding explicit "assign here" marker looks like rather natural idea to keep a reader in loop of what's happening there. [] -- Best regards, Paul mailto:pmiscml@gmail.com
czw., 12 lis 2020 o 19:41 Paul Sokolovsky <pmiscml@gmail.com> napisał(a):
Hello,
On Thu, 12 Nov 2020 09:55:10 -0800 Guido van Rossum <guido@python.org> wrote:
The position of PEP 622/634/535/636 authors is clear: we see this as a necessary feature to support using enums (e.g. Color.RED) or constants defined in other modules (e.g. re.I) when simple switch functionality is being migrated from literals (e.g. case 404) to named constants (e.g. case HTTPStatus.NOT_FOUND). Bothering users with the technicality of needing to use '==' here is a big usability hit.
As was pointed out many times on the mailing list, there's a very obvious way around needing to use '==' there. It's explicitly marking capturing terms in case's:
match foo: case ("foo", >val1): ... case ("bar", >val2): ...
I agree with that, though I would prefer using other symbol than > (? or $), one of reasons would by it would look better as "match all" target, other one that in future. it would allow extending syntax for simple guards like ?x < 100. -- 闇に隠れた黒い力 弱い心を操る
On Thu, Nov 12, 2020 at 09:40:02PM +0300, Paul Sokolovsky wrote:
match foo: case ("foo", >val1): ... case ("bar", >val2): ...
1. Much more intuitive for beginners. (If Python adopts it, I see other "user-friendly" languages adopting the same pattern in the coming decades).
I think you and I have a very different concept of "intuitive for beginners" here. I don't think that using the *greater than symbol* as a sigil for assignment would have been "intuitive" to me as a beginner, or anyone I have helped teach over the years. To me, that statement clearly and obviously could only mean one possible thing: * match a two-sequence where the first item equals "foo" and the second is greater than `val1`; (and similarly for the second case statement). Are there any other languages that use `>` as a prefix sigil to indicate assignment? If we were to use a sigil to represent binding, surely `=` would make more sense than `>`.
2. Upholds the rights of people who see "match" as glorified "switch" statement,
There is no right for people to dictate that syntax must support their misapprehensions about language features. Or for that matter, no right to dictate *anything* about syntax. There is no universal human right to dictate Python syntax. The best you have is the privilege to attempt to persuade others to support your preference, and for the Steering Council to be swayed by your arguments and/or the popular support for your preference.
and not keen on it doing assignments behind their backs. (The topic which was recently mentioned on the list.)
How is it doing assignments behind your back? The syntax is clear: a name is a binding pattern. That is as much an explicitly assignment statement as import, for, with...as, def or class. This is an assignment "behind your back": def sneaky_assignment(): global x x = 999 sneaky_assignment() There's nothing in the call to `sneaky_assignment` to hint that it assigns a value to the global `x`. Pattern matching is nothing like that: all binding patterns are explicit, all you need is to get past the misapprehension that pattern matching is a switch statement (it isn't!) and it will be clear as daylight: case 1, x: pass Of course x gets assigned to. It's a binding pattern. import sys Of course sys gets assigned to. It's an import.
3. Solves discrepancy with cases like:
# Why is this possible? obj.foo, obj.bar = val
# And this is not? match val: case obj.foo, obj.bar:
I agree with this. I think it is surprising that unqualified names are binding patterns but qualified names are not. That difference gives me pause. But using `>` as an assignment sigil is surely worse than the problem you hope to solve with it. -- Steve
Hello, On Fri, 13 Nov 2020 21:51:49 +1100 Steven D'Aprano <steve@pearwood.info> wrote:
match foo: case ("foo", >val1): ... case ("bar", >val2): ...
1. Much more intuitive for beginners. (If Python adopts it, I see other "user-friendly" languages adopting the same pattern in the coming decades).
I think you and I have a very different concept of "intuitive for beginners" here. I don't think that using the *greater than symbol* as a sigil for assignment would have been "intuitive" to me as a beginner, or anyone I have helped teach over the years.
Treat it as "arrow pointing into a variable identifier, meaning that value is getting into variable". ">>" and "->" are other alternatives with the same intuitive connotation. ">>" is a particularly interesting choice, as it should give warm fuzzy feelings (and partial moral compensation) to all folks who miss the print statement ('print >>sys.stderr, "foo"'). []
# Why is this possible? obj.foo, obj.bar = val
# And this is not? match val: case obj.foo, obj.bar:
I agree with this. I think it is surprising that unqualified names are binding patterns but qualified names are not. That difference gives me pause.
But *that's the problem* we're trying to solve! Aka, stop resolving binding-vs-value ambiguity by assigning semantic discrepancies to different *syntactic* patterns, and instead, consider using *punctuation* to resolve the ambiguity. And then there're 2 choices. 1. Use punctuation ("sigils") to mark as-value terms (expressions). This is now well (enough) covered in PEP642, from which this thread is, well, started. 2. Use punctuation ("sigils") to mark as-binding terms. This choice still seems to be under-considered. (As in: it doesn't seem like many people, including the PEP authors, tried to say "indeed, what if?" and feel thru it. I mean, try really hard. I trust the "gang of 4" spent maybe whole few hours on that and delivered "no" to all us. It's still not the same as dozens of people trying it over a few months).
But using `>` as an assignment sigil is surely worse than the problem you hope to solve with it.
">" is just a notation mark and one of many possible choices. ">", "->", ">>", "@", "$" were mentioned before, and today, even word-fulls like "bind" were proposed (thread "Words rather than sigils in Structural Pattern Matching"). All valid choices to consider, *once* we agree that it is a viable idea to mark bind-terms, on par with other alternatives, and not a throw-away "misconception", how PEP635 tries to represent it (https://www.python.org/dev/peps/pep-0635/#capture-patterns) -- Best regards, Paul mailto:pmiscml@gmail.com
Paul Sokolovsky wrote:
Use punctuation ("sigils") to mark as-binding terms. This choice still seems to be under-considered. (As in: it doesn't seem like many people, including the PEP authors, tried to say "indeed, what if?" and feel thru it. I mean, try really hard. I trust the "gang of 4" spent maybe whole few hours on that and delivered "no" to all us. It's still not the same as dozens of people trying it over a few months).
To anyone actually wondering how much time and mental energy we’ve spent on a particular issue: please take a look at our tracker before guessing “maybe whole few hours”: - Issue #1(!), April, 29 comments: https://github.com/gvanrossum/patma/issues/1 - Issue #90, June, 84 comments: https://github.com/gvanrossum/patma/issues/90 - Issue #92, June, 33 comments: https://github.com/gvanrossum/patma/issues/92 - Issue #105, June, 17 comments: https://github.com/gvanrossum/patma/issues/105 - Issue #143, August, 7 comments: https://github.com/gvanrossum/patma/issues/143 (I won't judge anyone for skimming a bit; it's a *lot* of discussion. Do note, though, that for months I was one of the proponents of store sigils like `?` until I was eventually convinced otherwise.) That's also not counting side-discussions in other issues, countless mailing list threads, two competing PEPs that make many of the same choices, a video call with the SC, etc. I'll also add, for anyone considering choosing yet another ASCII symbol off their keyboard and proposing it as a “novel”, “intuitive” marker: one problem with most of the hastily suggested adornments are that they do not nest very well, for even simple cases. Further, the fact that constructions like `p = Point(x, y)` look exactly the same as deconstructions like `case Point(x, y):` is absolutely intentional (which touches back on Guido’s “rhyme” comment last night). Very briefly, compare the current syntax: ``` case first, *middle, last: rebuilt = first, *middle, last case {"key": value, **rest}: rebuilt = {"key": value, **rest} case Point(x=a, y=b): rebuilt = Point(x=a, y=b) ``` with (using your own syntactic flavor): ``` case >first, *>middle, >last: rebuilt = first, *middle, last case {"key": >value, **>rest}: rebuilt = {"key": value, **rest} case Point(x=>a, y=>b): rebuilt = Point(x=a, y=b) ``` (I had to stop and think *hard* where exactly the `>` should go in `*middle` and `**rest`. I'm not confident I made the correct guess, either.)
On Fri, 13 Nov 2020 at 15:53, Brandt Bucher <brandtbucher@gmail.com> wrote:
Paul Sokolovsky wrote:
Use punctuation ("sigils") to mark as-binding terms. This choice still seems to be under-considered. (As in: it doesn't seem like many people, including the PEP authors, tried to say "indeed, what if?" and feel thru it. I mean, try really hard. I trust the "gang of 4" spent maybe whole few hours on that and delivered "no" to all us. It's still not the same as dozens of people trying it over a few months).
To anyone actually wondering how much time and mental energy we’ve spent on a particular issue: please take a look at our tracker before guessing “maybe whole few hours”:
- Issue #1(!), April, 29 comments: https://github.com/gvanrossum/patma/issues/1 - Issue #90, June, 84 comments: https://github.com/gvanrossum/patma/issues/90 - Issue #92, June, 33 comments: https://github.com/gvanrossum/patma/issues/92 - Issue #105, June, 17 comments: https://github.com/gvanrossum/patma/issues/105 - Issue #143, August, 7 comments: https://github.com/gvanrossum/patma/issues/143
(I won't judge anyone for skimming a bit; it's a *lot* of discussion. Do note, though, that for months I was one of the proponents of store sigils like `?` until I was eventually convinced otherwise.)
That's also not counting side-discussions in other issues, countless mailing list threads, two competing PEPs that make many of the same choices, a video call with the SC, etc.
I'll also add, for anyone considering choosing yet another ASCII symbol off their keyboard and proposing it as a “novel”, “intuitive” marker: one problem with most of the hastily suggested adornments are that they do not nest very well, for even simple cases. Further, the fact that constructions like `p = Point(x, y)` look exactly the same as deconstructions like `case Point(x, y):` is absolutely intentional (which touches back on Guido’s “rhyme” comment last night).
Very briefly, compare the current syntax:
``` case first, *middle, last: rebuilt = first, *middle, last case {"key": value, **rest}: rebuilt = {"key": value, **rest} case Point(x=a, y=b): rebuilt = Point(x=a, y=b) ```
with (using your own syntactic flavor):
``` case >first, *>middle, >last: rebuilt = first, *middle, last case {"key": >value, **>rest}: rebuilt = {"key": value, **rest} case Point(x=>a, y=>b): rebuilt = Point(x=a, y=b) ```
Well, this example is a bit unfair, since you don't present a case where there would be matching values in variables that we would want to compare - which is the solution that is being brought up. And even in that case, while I can see: case Point(x=>a, y=>b): and immediately read it as "attribute x from point goes into a", the line in the current proposal doing the same: case Point(x=a, y=b): is far from being immediately obvious (Am I creating a new Point? Am i assigning "a" to "x"? If so, where does "a" come from??)
(I had to stop and think *hard* where exactly the `>` should go in `*middle` and `**rest`. I'm not confident I made the correct guess, either.) _______________________________________________ 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/7SJ2SOPR... Code of Conduct: http://python.org/psf/codeofconduct/
I *hope* this was a typo! If case Point(x=a, y=b): assigns to a and b (instead of x and y, as in a normal call), then that is ... going to be very easy for me to forget, and to miss even when I'm aware of it. -jJ
On Fri, 13 Nov 2020 at 17:36, Jim J. Jewett <jimjjewett@gmail.com> wrote:
I *hope* this was a typo! If
case Point(x=a, y=b):
assigns to a and b (instead of x and y, as in a normal call), then that is ... going to be very easy for me to forget, and to miss even when I'm aware of it.
No typo - this is _precisely_what the main proposal on PEPs 634, 635 and 636 is suggesting, and tha PEP 642 is trying to avoid. Here it is working as is on my Python with PEP 622 build: ``` Python 3.10.0a0 (heads/patma:1ba56a003b, Aug 6 2020, 02:00:58) Type 'copyright', 'credits' or 'license' for more information IPython 7.17.0 -- An enhanced Interactive Python. Type '?' for help. In [1]: from dataclasses import dataclass In [2]: @dataclass ...: class Point: ...: x: float ...: y: float ...: In [3]: def get_coords(p): ...: match p: ...: case Point(x=a, y=b): ...: return a, b ...: case _: ...: raise TypeError() ...: In [4]: get_coords(Point(3, 4)) Out[4]: (3, 4) ```
-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/F66J72JU... Code of Conduct: http://python.org/psf/codeofconduct/
On 11/13/2020 1:48 PM, Joao S. O. Bueno wrote:
On Fri, 13 Nov 2020 at 17:36, Jim J. Jewett <jimjjewett@gmail.com <mailto:jimjjewett@gmail.com>> wrote:
I *hope* this was a typo! If
case Point(x=a, y=b):
assigns to a and b (instead of x and y, as in a normal call), then that is ... going to be very easy for me to forget, and to miss even when I'm aware of it.
No typo - this is _precisely_what the main proposal on PEPs 634, 635 and 636 is suggesting, and tha PEP 642 is trying to avoid.
And the claim is, that there are people that think this is a good idea❓❓ And are actually proposing to add it to Python❓
Here it is working as is on my Python with PEP 622 build:
``` Python 3.10.0a0 (heads/patma:1ba56a003b, Aug 6 2020, 02:00:58) Type 'copyright', 'credits' or 'license' for more information IPython 7.17.0 -- An enhanced Interactive Python. Type '?' for help.
In [1]: fromdataclassesimportdataclass
In [2]: @dataclass ...: classPoint: ...: x: float ...: y: float ...:
In [3]: defget_coords(p): ...: match p: ...: case Point(x=a, y=b): ...: returna, b ...: case _: ...: raiseTypeError() ...:
In [4]: get_coords(Point(3, 4)) Out[4]: (3, 4)
```
-jJ
On Sat, 14 Nov 2020 at 07:55, Joao S. O. Bueno <jsbueno@python.org.br> wrote:
On Fri, 13 Nov 2020 at 17:36, Jim J. Jewett <jimjjewett@gmail.com> wrote:
I *hope* this was a typo! If
case Point(x=a, y=b):
assigns to a and b (instead of x and y, as in a normal call), then that is ... going to be very easy for me to forget, and to miss even when I'm aware of it.
No typo - this is _precisely_what the main proposal on PEPs 634, 635 and 636 is suggesting, and tha PEP 642 is trying to avoid.
PEP 642 isn't trying to avoid it yet, as it wasn't something that had previously occurred to me as a possible problem (assigning to a "function call" is already illegal syntax, so PEP 642 currently inherits the spelling of class patterns unchanged from PEP 634, and the same is also mostly true for mapping patterns). Now that the point has been raised, though, my idea for addressing it would be somewhat similar to the fix applied for walrus patterns between PEP 622 and PEP 634: * To capture a mapping key or instance attribute, don't use ":" or "=", use "as" * You would only use ":" or "=" if you wanted to specify a subpattern to match the value against * Specifying an irrefutable pattern other than the wildcard pattern on a mapping key or instance attribute would be a syntax error That approach would give the following: case Point(x as a, y as b): ... # A Point object with x & y attributes, capturing those to "a" and "b" case object(x=__, y=__): ... # Any object with x & y attributes, not capturing anything case object(x=a, y=b): ... # Syntax Error (matching instance attribute against a non-wildcard irrefutable pattern) case {"x" as a, "y" as b): ... # A mapping with "x" & "y" keys, capturing those to "a" and "b" case {"x":__, "y":__}: ... # A mapping with "x" & "y" keys, not capturing anything case {"x":a, "y":b}: ... # Syntax Error (matching mapping value against a non-wildcard irrefutable pattern) Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia
On 14/11/20 9:33 am, Jim J. Jewett wrote:
I *hope* this was a typo! If
case Point(x=a, y=b):
assigns to a and b (instead of x and y, as in a normal call), then that is ... going to be very easy for me to forget, and to miss even when I'm aware of it.
I don't think it is a typo, unfortunately. I share this concern, and it's one of the reasons I would prefer assignments to be explicitly marked. With case Point(x=?a, y=?b): then if you get it wrong and write case Point(?a=x, ?b=y): at least you'll get a syntax error. -- Greg
Jim J. Jewett writes:
I *hope* this was a typo! If
case Point(x=a, y=b):
assigns to a and b (instead of x and y, as in a normal call), then that is ... going to be very easy for me to forget, and to miss even when I'm aware of it.
I don't argue with your main point as a general principle, but I think I myself would probably be OK with real code where Points are probably used quite frequently (instead of being introduced in this line ;-) and the identifiers being bound aren't named "a" and "b". Steve
On 14/11/20 7:45 am, Brandt Bucher wrote:
with (using your own syntactic flavor): ``` case >first, *>middle, >last: rebuilt = first, *middle, last case {"key": >value, **>rest}: rebuilt = {"key": value, **rest} case Point(x=>a, y=>b): rebuilt = Point(x=a, y=b)
I think this is a case where syntax matters. To my eyes this looks far less confusing: case ?first, *?middle, ?last: rebuilt = first, *middle, last case {"key": ?value, **?rest}: rebuilt = {"key": value, **rest} case Point(x=?a, y=?b): rebuilt = Point(x=a, y=b)
(I had to stop and think *hard* where exactly the `>` should go in `*middle` and `**rest`.
There's a simple rule -- the "?" goes directly in front of the thing being assigned. You're assigning to 'middle', not '*middle', so it's '*?middle', not '?*middle'. I know the same rule applies whatever sigil is being used, but to my way of thinking, '>' is too easily confused with a comparison operator. Also it's tempting to interpret '=>' as a single token, which accidentally happens to make sense here, but could mislead people into writing '*=>middle' instead of '*>middle'. -- Greg
On Sat, 14 Nov 2020 at 09:51, Greg Ewing <greg.ewing@canterbury.ac.nz> wrote:
On 14/11/20 7:45 am, Brandt Bucher wrote:
with (using your own syntactic flavor): ``` case >first, *>middle, >last: rebuilt = first, *middle, last case {"key": >value, **>rest}: rebuilt = {"key": value, **rest} case Point(x=>a, y=>b): rebuilt = Point(x=a, y=b)
I think this is a case where syntax matters. To my eyes this looks far less confusing:
case ?first, *?middle, ?last: rebuilt = first, *middle, last case {"key": ?value, **?rest}: rebuilt = {"key": value, **rest} case Point(x=?a, y=?b): rebuilt = Point(x=a, y=b)
Based on the discussion in this thread, v3 of PEP 642 is going to propose spelling these as: case first, *middle, last: rebuilt = first, *middle, last case {"key" as value, **rest}: rebuilt = {"key": value, **rest} case Point(x as a, y as b): rebuilt = Point(x=a, y=b) I'm in agreement with the PEP 634 authors that we want to keep sequence pattern matching consistent with iterable unpacking as far as name binding is concerned. Mapping patterns and class patterns are both completely new though, and I think the readability problem there is quite similar to the one that existed with walrus patterns in PEP 622, and thus amenable to a similar solution (i.e. spell the capture patterns for those cases with `as`, not `:` or `=`). Cheers, Nick. P.S. I've started my TODO list for v3 at https://github.com/ncoghlan/peps/issues/6 -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia
On Sat, Nov 14, 2020 at 7:54 AM Nick Coghlan <ncoghlan@gmail.com> wrote:
On Sat, 14 Nov 2020 at 09:51, Greg Ewing <greg.ewing@canterbury.ac.nz> wrote:
On 14/11/20 7:45 am, Brandt Bucher wrote:
with (using your own syntactic flavor): ``` case >first, *>middle, >last: rebuilt = first, *middle, last case {"key": >value, **>rest}: rebuilt = {"key": value, **rest} case Point(x=>a, y=>b): rebuilt = Point(x=a, y=b)
I think this is a case where syntax matters. To my eyes this looks far less confusing:
case ?first, *?middle, ?last: rebuilt = first, *middle, last case {"key": ?value, **?rest}: rebuilt = {"key": value, **rest} case Point(x=?a, y=?b): rebuilt = Point(x=a, y=b)
Based on the discussion in this thread, v3 of PEP 642 is going to propose spelling these as:
case first, *middle, last: rebuilt = first, *middle, last case {"key" as value, **rest}: rebuilt = {"key": value, **rest} case Point(x as a, y as b): rebuilt = Point(x=a, y=b)
I'm in agreement with the PEP 634 authors that we want to keep sequence pattern matching consistent with iterable unpacking as far as name binding is concerned. Mapping patterns and class patterns are both completely new though, and I think the readability problem there is quite similar to the one that existed with walrus patterns in PEP 622, and thus amenable to a similar solution (i.e. spell the capture patterns for those cases with `as`, not `:` or `=`).
FWIW, I'd like to add my +1 to usage of "as" for spelling class capture patterns. This is by far the clearest and easiest to read form I've seen thus far, and I suspect that it would be the easiest to explain to users already familiar with usage of "as" from other areas in Python. A new feature being as distinguishable as possible and easy to explain to existing users is very important in my book, and based on the responses, I think that the current "=" form used in PEP 634 for matching class patterns would be substantially more difficult for users to mentally parse and understand compared to "as". It's also worth considering new Python users that might have general OO experience but not with robust pattern matching (e.g. Java-heavy backgrounds). I could definitely see "case Point(x=a, y=b):" being confused for instantiation, whereas usage of "as" makes it more clear that something else is happening (hopefully leading them to search around for more info about Python pattern matching).
On Sun, Nov 15, 2020 at 4:28 PM Kyle Stanley <aeros167@gmail.com> wrote:
FWIW, I'd like to add my +1 to usage of "as" for spelling class capture patterns. This is by far the clearest and easiest to read form I've seen thus far, and I suspect that it would be the easiest to explain to users already familiar with usage of "as" from other areas in Python. A new feature being as distinguishable as possible and easy to explain to existing users is very important in my book, and based on the responses, I think that the current "=" form used in PEP 634 for matching class patterns would be substantially more difficult for users to mentally parse and understand compared to "as".
It's also worth considering new Python users that might have general OO experience but not with robust pattern matching (e.g. Java-heavy backgrounds). I could definitely see "case Point(x=a, y=b):" being confused for instantiation, whereas usage of "as" makes it more clear that something else is happening (hopefully leading them to search around for more info about Python pattern matching).
case Point(x=as a, y=as b): That doesn't read well to me. Or is there some other spelling of 'as' that makes better sense to you? ChrisA (why am I responding to this topic? I'm really not sure.)
On Sun, Nov 15, 2020 at 1:56 AM Chris Angelico <rosuav@gmail.com> wrote:
On Sun, Nov 15, 2020 at 4:28 PM Kyle Stanley <aeros167@gmail.com> wrote:
FWIW, I'd like to add my +1 to usage of "as" for spelling class capture
patterns. This is by far the clearest and easiest to read form I've seen thus far, and I suspect that it would be the easiest to explain to users already familiar with usage of "as" from other areas in Python. A new feature being as distinguishable as possible and easy to explain to existing users is very important in my book, and based on the responses, I think that the current "=" form used in PEP 634 for matching class patterns would be substantially more difficult for users to mentally parse and understand compared to "as".
It's also worth considering new Python users that might have general OO
experience but not with robust pattern matching (e.g. Java-heavy backgrounds). I could definitely see "case Point(x=a, y=b):" being confused for instantiation, whereas usage of "as" makes it more clear that something else is happening (hopefully leading them to search around for more info about Python pattern matching).
case Point(x=as a, y=as b):
That doesn't read well to me.
Or is there some other spelling of 'as' that makes better sense to you?
The post from Nick that I was primarily replying to used the following spelling: "case Point(x as a, y as b):".
But Point(x as a) already has a meaning in PEP 634; it’s a positional argument captured in x *and* in a. (Previously spelled as Point(a := x). The phrase ‘as a’ can be added after any pattern to *also* capture it in ‘a’. More typically used as e.g.‘Pattern(x, y) as p’, which captures the first two fields in x and y, and the whole Point in p. On Sat, Nov 14, 2020 at 23:06 Kyle Stanley <aeros167@gmail.com> wrote:
On Sun, Nov 15, 2020 at 1:56 AM Chris Angelico <rosuav@gmail.com> wrote:
On Sun, Nov 15, 2020 at 4:28 PM Kyle Stanley <aeros167@gmail.com> wrote:
FWIW, I'd like to add my +1 to usage of "as" for spelling class capture
patterns. This is by far the clearest and easiest to read form I've seen thus far, and I suspect that it would be the easiest to explain to users already familiar with usage of "as" from other areas in Python. A new feature being as distinguishable as possible and easy to explain to existing users is very important in my book, and based on the responses, I think that the current "=" form used in PEP 634 for matching class patterns would be substantially more difficult for users to mentally parse and understand compared to "as".
It's also worth considering new Python users that might have general OO
experience but not with robust pattern matching (e.g. Java-heavy backgrounds). I could definitely see "case Point(x=a, y=b):" being confused for instantiation, whereas usage of "as" makes it more clear that something else is happening (hopefully leading them to search around for more info about Python pattern matching).
case Point(x=as a, y=as b):
That doesn't read well to me.
Or is there some other spelling of 'as' that makes better sense to you?
The post from Nick that I was primarily replying to used the following spelling: "case Point(x as a, y as b):". _______________________________________________ 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/JBSWERRH... Code of Conduct: http://python.org/psf/codeofconduct/
-- --Guido (mobile)
On Sun., 15 Nov. 2020, 5:25 pm Guido van Rossum, <guido@python.org> wrote:
But Point(x as a) already has a meaning in PEP 634; it’s a positional argument captured in x *and* in a. (Previously spelled as Point(a := x). The phrase ‘as a’ can be added after any pattern to *also* capture it in ‘a’. More typically used as e.g.‘Pattern(x, y) as p’, which captures the first two fields in x and y, and the whole Point in p.
Indeed, the proposed change I'm contemplating for class matching would require that positional matching be opt-in rather than the default. The default would instead become to check that the named attributes exist, so "Pattern(x, y)" would be short for "Pattern(x=__, y=__)", and you'd have to write "Pattern(x, y, /)" instead to request positional arg matching. The default behaviour of class patterns would become a lot more like mapping patterns, but working off attribute names rather than keys. I think that will give an end result that offers the same capabilities as PEP 634, but the proof will be in the reference implementation update. Cheers, Nick.
Hello, On Sun, 15 Nov 2020 00:22:01 -0500 Kyle Stanley <aeros167@gmail.com> wrote: []
FWIW, I'd like to add my +1 to usage of "as" for spelling class capture patterns.
If you want to use "as" in spelling of class capture patterns, you don't need to worry about anything, because PEP634 already allows that: case Point(x=_ as a, y=_ as b): (better spelled as: case Point(x = _ as a, y = _ as b): ) You need to worry only if: 1. You find that the "as" form is too verbose, and strongly believe that the same expressive means can be achieved in more concise syntax. 2. If you worry that other people will still write "case Point(x=a, y=b)" and that will confuse you and/or yet other people. For p.2, combination of p.1 and switching default syntax to be value patterns offers an interesting solution. (Solution to force everyone to write long verbose "as" patterns, or ambiguous "as" patterns, aren't "interesting" IMHO). -- Best regards, Paul mailto:pmiscml@gmail.com
Matching *should* look like instantiation ... case Point(2, 4) *should* mean "Does it match the object that Point(2, 4) would create?". case Point(2, y=4) is less crucial, because they *could* rewrite the call -- but why should they have to? Changing from constants, and case Point(x=a, y=b) suddenly means x is the already externally bound name and *a* is being assigned to, so it doesn't need to have been defined previously? What advantage can there be in re-using syntax to mean something opposite to what it normally does? Others have objected to both case Point(x as a) and case Point(a:=x) # I dislike it, but it isn't as bad as the raw = but I am missing the problem, other than the confusion binding always brings. To me, they do both seem to say "It matches the object that would be created by Point(x) for *some* x, and an example/witness x that works is now stored in a. If there is no way to resolve this, I would honestly prefer to require nested matching, vs using call signatures in a way opposite to their normal usage. -jJ
Jim J. Jewett writes:
What advantage can there be in re-using syntax to mean something opposite to what it normally does?
In math, it allows us to write "solve c = f(x) for x". That doesn't mean "bind c to the value f(x)", it means exactly the opposite. No problem here, I suppose. So match p: case Point(x=a, y=b): is a way of saying "solve p = Point(x=a, y=b) for a and b". I understand your distaste for this syntax, but I see no problem in principle. It's a problem of programmer habits and the evident inconsistency with forms like "case Point(x=1, y=2)". This is especially true when a or b is already bound.
On 11/15/2020 11:18 PM, Stephen J. Turnbull wrote:
Jim J. Jewett writes:
What advantage can there be in re-using syntax to mean something opposite to what it normally does?
In math, it allows us to write "solve c = f(x) for x". That doesn't mean "bind c to the value f(x)", it means exactly the opposite. No problem here, I suppose. So
match p: case Point(x=a, y=b):
is a way of saying "solve p = Point(x=a, y=b) for a and b".
I understand your distaste for this syntax, but I see no problem in principle. It's a problem of programmer habits and the evident inconsistency with forms like "case Point(x=1, y=2)". This is especially true when a or b is already bound. Indeed. Mathematics never came up with separate symbols for equality and assignment. Neither did early programming languages. That was a source of confusion for many programmers.
Then someone invented == for equality comparison, and = for assignment, or alternately := for assignment and = for equality comparison. Python now has the first three, many other languages only have one of the pairs. This reduced the confusion and resulting bugs, although some still happen. Linters help avoid them, and even some compilers emit warnings for possibly misused operators of those pairs. In mathematics, equality might be written a = b or b = a, transitively irrelevant. But I have never seen assignment in mathematics be anything but var = value, as in "let x = 3" or "let x = <some constant or expression>". Maybe I'm just uninformed regarding current practice, but I do have a degree in mathematics, albeit somewhat dated at this point. So I also have a distaste for any syntax that puts an assignment target on the right, it seems like a step toward reintroducing confusion and bugs. The pattern match operator seems complex enough without (re-)introducing confusion regarding assignment operators. In your example "solve c = f(x) for x", that is not an assignment operator, but an equality comparison operator in an equation. Although I know a few exist, I'm not familiar with programs that do symbolic algebra, to know how they notate such instructions: most programming language do not do symbolic manipulations. But note that your example is wordier than "let c = f(x)" which would be an assignment operation. And note that it _needs to be wordier_ to convey the proper mathematical semantics. At least, it did back when I was in math classes. Just because something is syntactically unambiguous, doesn't mean it makes a good user interface.
On 2020-11-16 08:54, Glenn Linderman wrote:
On 11/15/2020 11:18 PM, Stephen J. Turnbull wrote:
Jim J. Jewett writes:
What advantage can there be in re-using syntax to mean something opposite to what it normally does?
In math, it allows us to write "solve c = f(x) for x". That doesn't mean "bind c to the value f(x)", it means exactly the opposite. No problem here, I suppose. So
match p: case Point(x=a, y=b):
is a way of saying "solve p = Point(x=a, y=b) for a and b".
I understand your distaste for this syntax, but I see no problem in principle. It's a problem of programmer habits and the evident inconsistency with forms like "case Point(x=1, y=2)". This is especially true when a or b is already bound. Indeed. Mathematics never came up with separate symbols for equality and assignment. Neither did early programming languages. That was a source of confusion for many programmers.
[snip] Fortran (1954) used '=' for assignment and '.EQ.' for equality. Algol (1958) used ':=' for assignment and '=' for equality.
Glenn Linderman writes:
Mathematics never came up with separate symbols for equality and assignment.
Mathematics doesn't need them, until we come to an age where we do mathematics on algorithms. It's perfectly possible to do algebra interpreting "let x = 3" as an equation of the form "f(x) = g(x)" rather than an assignment.
In your example "solve c = f(x) for x", that is not an assignment operator, but an equality comparison operator in an equation.
But "=" is sugar, not syntax, in the "let" form, and although it is syntax in the "solve" form, in both cases it is the keyword "let" or "solve" that denotes assignment. So "solve c = f(x) for x" *can* be interpreted as an assignment to x.
But note that your example is wordier than "let c = f(x)" which would be an assignment operation. And note that it _needs to be wordier_ to convey the proper mathematical semantics.
Wordiness in defense of readability is no sin, at least not in Python. :-) In exactly the same way as you describe for the "solve" example, a destructuring pattern match is necessarily wordier than simple assignments to the component variables would be. So I don't see an issue here.
Just because something is syntactically unambiguous, doesn't mean it makes a good user interface.
I didn't (and don't) argue it does. I argue it works for me, and if it works for Guido too, I refuse to feel bad about that. ;-) If it doesn't work for a large majority of people who would use pattern matching in Python, who would want to destructure "Point(x=a,y=b)", it's bad UI. I don't know that's true yet, so I want to oppose false statements like "there's no analogy to this" (which is not quite what Jim said). Tastes differ, those differences are valid, and to some extent the majority rules here (although I've seen in the past that some folks are much better judges of *future* majorities than others! ;-) Steve
On 18/11/20 5:29 pm, Stephen J. Turnbull wrote:
Glenn Linderman writes:
Mathematics never came up with separate symbols for equality and assignment.
Mathematics doesn't need them, until we come to an age where we do mathematics on algorithms.
Even then, when mathematicians describe algorithms they often use subscripts to disinguish different values of a variable on different iterations, effectively making them into different variables. So they still don't need a symbol for assignment. -- Greg
Hello, On Fri, 13 Nov 2020 18:45:55 -0000 "Brandt Bucher" <brandtbucher@gmail.com> wrote:
Paul Sokolovsky wrote:
Use punctuation ("sigils") to mark as-binding terms. This choice still seems to be under-considered. (As in: it doesn't seem like many people, including the PEP authors, tried to say "indeed, what if?" and feel thru it. I mean, try really hard. I trust the "gang of 4" spent maybe whole few hours on that and delivered "no" to all us. It's still not the same as dozens of people trying it over a few months).
To anyone actually wondering how much time and mental energy we’ve spent on a particular issue: please take a look at our tracker before guessing “maybe whole few hours”:
Thanks for the very useful response. (Which follows another useful from another PEP author, Tobias Kohn, https://mail.python.org/archives/list/python-dev@python.org/thread/FYGTU4RMZ...). Thanks gentlemen for still keeping up the discussion even if you went thru all those matter many times.
- Issue #1(!), April, 29 comments: https://github.com/gvanrossum/patma/issues/1 - Issue #90, June, 84 comments: https://github.com/gvanrossum/patma/issues/90 - Issue #92, June, 33 comments: https://github.com/gvanrossum/patma/issues/92 - Issue #105, June, 17 comments: https://github.com/gvanrossum/patma/issues/105 - Issue #143, August, 7 comments: https://github.com/gvanrossum/patma/issues/143
(I won't judge anyone for skimming a bit; it's a *lot* of discussion.
I have to admit that I didn't read thru it. And fairly speaking, my aim is not to argue with the PEP authors, but "raise awareness" of the implications of choices made by PEP634 (and that the choice made there is not the "absolute winner", but more and more look like a leap of faith among other viable choices.) Anyway, given that you even included the # of messages above, let me still do some homework and add to stats number of participants in the ticket thread above (as an indirect way to assess community outreach): 5 + 12 + 8 + 6 + 5 I'm not sure what to do with these numbers (doing max() perhaps?). It's clear that the discussions there are more active than on the mailing list.
Do note, though, that for months I was one of the proponents of store sigils like `?` until I was eventually convinced otherwise.)
That's another great answer! Given that PEP622 had 6 authors, it's pretty mathematically clear that there should have been proponents of all 3 load/store options, and I wondered who's who. []
I'll also add, for anyone considering choosing yet another ASCII symbol off their keyboard and proposing it as a “novel”, “intuitive” marker: one problem with most of the hastily suggested adornments are
I don't think the problem is "hastily suggested <foo>". The problem is more that: despite all your great and multiple considerations, finding a compromise among you 6, compressing it to a small paragraph of PEP635, with culminating sentence in it starting with "However, this is based on the misconception", which sets the tone very well - despite all this great work, there're still people who think that you didn't do fairness to the idea of marking the stores. A possible solution would have been to extend discussion of this option in PEP635, and start with considering what would be lost by *not* adopting that approach, instead of coloring it all in a dismissive tone from the start. I know that might have been hard. As we know, an "alternative" PEP 642 was spawned exactly out of rejection of additional information regarding "sigils for loads" idea: https://github.com/python/peps/pull/1564
that they do not nest very well, for even simple cases.
I propose to add a unary prefix operator (choices among ">", ">>", "->", "@", etc.) Those do nest well. Some are completely unambiguous.
Further, the fact that constructions like `p = Point(x, y)` look exactly the same as deconstructions like `case Point(x, y):` is absolutely intentional (which touches back on Guido’s “rhyme” comment last night).
I don't think that "exactly the same" is the right words, or expectations to have. For example, PEP622 used phrase "It would break the syntactic parallels of the current grammar". And that's the whole point: `case Point(>x, >y)` is exactly parallel to `p = Point(x, y)`! The only difference is that the bind-to terms (here, the variables) are explicitly marked. Consider if the language had a color as syntactic means. Then in `p = Point(x, y)`, x and y would be colored in one way, but in `case Point(x, y)` - in different way. But they would be exactly parallel, and maybe even "the same". Thankfully, we don't use colors as syntactic means. The closest device we have is punctuation, and that's where idea to use sigils come from.
Very briefly, compare the current syntax:
``` case first, *middle, last: rebuilt = first, *middle, last case {"key": value, **rest}: rebuilt = {"key": value, **rest} case Point(x=a, y=b): rebuilt = Point(x=a, y=b) ```
with (using your own syntactic flavor):
``` case >first, *>middle, >last: rebuilt = first, *middle, last case {"key": >value, **>rest}: rebuilt = {"key": value, **rest} case Point(x=>a, y=>b): rebuilt = Point(x=a, y=b) ```
(I had to stop and think *hard* where exactly the `>` should go in `*middle` and `**rest`. I'm not confident I made the correct guess, either.)
In my idea, ">" (or the like) would be a kind of low-precedence unary operator with only comma "," being of lower precedence. It would be written correspondingly, at the outermost level of the term, e.g.: case >first, >*middle, >last: rebuilt = first, *middle, last case {"key": >value, >**rest}: rebuilt = {"key": value, **rest} case Point(x = >a, y = >b): # Space is mandatory here, why I think ">" # alone would not be adopted. So, you say compare it with PEP634? But that's how I arrived here! Months after first reading initial PEP622 and being sleep-walked thru that option by it ("No other language use that option, so we don't want either" - "No, of course not, sir!") - I decide to think "what if", and write down something like the above. And I have to say you, it doesn't look that bad! It resolves a hard gripe I have with PEP622/634, that it can't do: MY_LOVELY_CONSTANT = 1 case MY_LOVELY_CONSTANT: But beyond that, it also makes clear to even kids what's being captured, and what's not. And just as we speak, real fun only starts. The echo just starts to reach the wider community which starts to think what stuff in PEP634 *really* means. https://mail.python.org/archives/list/python-dev@python.org/message/F66J72JU... is only a first in a wave of "d'oh" emails. Can't say I expect there would a zunami, but one can easily expect a long, persistent, not subsiding trickle of those. But not only novices (novices in Python, but also novices in pattern matching) are confused. In https://mail.python.org/archives/list/python-dev@python.org/message/Q2ARJULL... , a core Python developer publicly admits "it wasn't something that had previously occurred to me as a possible problem". I.e. he read PEPs all this time, got some issues with them (caused him to submit an "elaboration" PEP), but he didn't see *all* issues with them. Dear Brandt, please hang on with us, the wider Python community, as it starts to dawn on us. The real fun just begins. -- Best regards, Paul mailto:pmiscml@gmail.com
Hi, Le 12/11/2020 à 18:55, Guido van Rossum a écrit :
The position of PEP 622/634/535/636 authors is clear:
well, let me first emphasize that I did *not* mean to reopen the discussion on those PEPs, which explain and discuss their design choices thoroughly (even better since the rewrite, thanks for that). And I definitely did not mean to spawn another "mark capture or value" subthread… I thought "PEP 642 v2" in the thread title was explicit enough, should have been more cautious :-) PEP 642 states as a design principle that parallelism between patterns and assignments should be kept as much as possible (let's not discuss this principle here). Thus, introducing different semantics for dotted names deserves a discussion in that PEP (by contrast, literal constraints need little discussion, because they have no semantics in assignments).
we see this as a necessary feature to support using enums (e.g. Color.RED) or constants defined in other modules (e.g. re.I) when simple switch functionality is being migrated from literals (e.g. case 404) to named constants (e.g. case HTTPStatus.NOT_FOUND). Bothering users with the technicality of needing to use '==' here is a big usability hit.
Indeed, enums and other dotted constants are the heart of the matter. And I get your point about not making useful refactoring more difficult. Still it could make sense (in the philosophy of PEP 642, again) to defer the choice and see how strong the need is. What PEP 642 ends up proposing will be Nick Coghlan's call. Cheers, Baptiste P.S.: a few examples for "taste": # your example match status: case == HTTPStatus.NOT_FOUND: ... vs. case HTTPStatus.NOT_FOUND: # worst-case where constants are buried in the pattern match sock: case socket(family=(==socket.AF_INET), type=(==socket.SOCK_STREAM)): ... vs. case socket(family=socket.AF_INET, type=socket.SOCK_STREAM): # same with plain constants, PEP 642 only match sock: case socket(family=(==AF_INET), type=(==SOCK_STREAM)): ...
On Sat, 14 Nov 2020 at 01:59, Baptiste Carvello <devel2020@baptiste-carvello.net> wrote:
Hi,
Le 12/11/2020 à 18:55, Guido van Rossum a écrit :
The position of PEP 622/634/535/636 authors is clear:
well, let me first emphasize that I did *not* mean to reopen the discussion on those PEPs, which explain and discuss their design choices thoroughly (even better since the rewrite, thanks for that). And I definitely did not mean to spawn another "mark capture or value" subthread… I thought "PEP 642 v2" in the thread title was explicit enough, should have been more cautious :-)
PEP 642 states as a design principle that parallelism between patterns and assignments should be kept as much as possible (let's not discuss this principle here). Thus, introducing different semantics for dotted names deserves a discussion in that PEP (by contrast, literal constraints need little discussion, because they have no semantics in assignments).
You're right, I had missed that I didn't mention attribute syntax specifically in https://www.python.org/dev/peps/pep-0642/#keeping-inferred-equality-constrai... The rationale is the same as it is in PEP 635: comparing against enum values is likely to be super common, and requiring the extra "==" sigils in that case at least arguably hinders readability rather than helping it. I actually find most of the predictions of likely usage patterns in PEP 635 entirely plausible - where I differ with the authors of that PEP is in whether or not we need to offer explicit override syntax for the cases where those predictions turn out to be wrong, rather than in our opinions of what the most common use cases are actually going to be.
we see this as a necessary feature to support using enums (e.g. Color.RED) or constants defined in other modules (e.g. re.I) when simple switch functionality is being migrated from literals (e.g. case 404) to named constants (e.g. case HTTPStatus.NOT_FOUND). Bothering users with the technicality of needing to use '==' here is a big usability hit.
Indeed, enums and other dotted constants are the heart of the matter. And I get your point about not making useful refactoring more difficult. Still it could make sense (in the philosophy of PEP 642, again) to defer the choice and see how strong the need is. What PEP 642 ends up proposing will be Nick Coghlan's call.
I opted to include the inferred equality constraints for attributes specifically to make the revised PEP 642 almost purely additive over PEP 634 - while v1 removed a lot of things (which raised several legitimate readability and usability concerns), the only things v2 outright removes are the inferred constraints for True and False (on grounds of ambiguity). The rest of the changes are now either new additions (explicit identity and equality constraints), changes in spelling (double-underscore vs single-underscore for wildcards), or slight changes in how constructs are defined (the inferred constraints for literals and attribute lookups get redefined as syntactic sugar for their explicit counterparts, rather than being first class constructs in their own right). Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia
On Fri., 13 Nov. 2020, 4:01 am Guido van Rossum, <guido@python.org> wrote:
The position of PEP 622/634/535/636 authors is clear: we see this as a necessary feature to support using enums (e.g. Color.RED) or constants defined in other modules (e.g. re.I) when simple switch functionality is being migrated from literals (e.g. case 404) to named constants (e.g. case HTTPStatus.NOT_FOUND). Bothering users with the technicality of needing to use '==' here is a big usability hit.
Right, this was a part of Steven D'Aprano's counterproposal that I found compelling, so PEP 642 now keeps the inferred equality constraints for the patterns that are unambiguous in context. The "==" is only required when the expression would otherwise be interpreted as a capture pattern, or wouldn't be allowed in a pattern at all. Cheers, Nick.
On Thu, Nov 12, 2020 at 7:38 AM Baptiste Carvello < devel2020@baptiste-carvello.net> wrote:
Hi,
Le 08/11/2020 à 07:47, Nick Coghlan a écrit :
Hi folks,
I have updated PEP 642 significantly based on the feedback received over the past week.
[...] a change that I feel is insufficiently discussed is the choice to have "attr_constraint" as an inferred constraint. I can think of arguments to defer it for now at least:
* it is a one way door (if dotted names are made a constraint pattern now, they can't become a capture pattern later);
* it makes a difference from assignment target syntax, where you can assign to a dotted name;
* the shorthand notation is less valuable than for literals, as dotted names are verbose already, 3 more characters make little difference;
* the user has no explicit syntax to override the inferred semantics.
I feel like some discussion of this choice in the PEP would make sense.
Cheers, Baptiste _______________________________________________ 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/RQPUV7PA... Code of Conduct: http://python.org/psf/codeofconduct/
-- --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-c...> _______________________________________________ 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/DPDHLPKA... Code of Conduct: http://python.org/psf/codeofconduct/
participants (15)
-
Baptiste Carvello
-
Brandt Bucher
-
Chris Angelico
-
Glenn Linderman
-
Greg Ewing
-
Guido van Rossum
-
Jim J. Jewett
-
Joao S. O. Bueno
-
Kyle Stanley
-
MRAB
-
Nick Coghlan
-
Paul Sokolovsky
-
Piotr Duda
-
Stephen J. Turnbull
-
Steven D'Aprano