Words rather than sigils in Structural Pattern Matching
I have read a great deal of discussion on the pattern matching PEPs and less formal discussions. It is possible I have overlooked some post in all of that, of course. ... OK, just saw Guido's "wait for new SC" comment, which I suppose applies to this too :-). One idea that I cannot recall seeing, but that seems to make sense to me and fit with Python's feel is using a WORD to distinguish between a variable value and a binding target. That is, instead of a special symbol prefixing or suffixing a name, either to indicate it is or is not a binding target. Of course, whether the extra word would be used for binding or for NOT binding is a question still. NOT_FOUND = 404 match http_code: case 200: print("OK document") case value NOT_FOUND: # use the variable value print("Document not found") case OTHER_CODE: # bind this name print("Other HTTP code", OTHER_CODE) Of course, this would require a soft keyword, which is a disadvantage. Going the other direction: NOT_FOUND = 404 match http_code: case 200: print("OK document") case NOT_FOUND: # use the variable value print("Document not found") case bind OTHER_CODE: # bind this name print("Other HTTP code") To me these read better than the punctuation characters. But I guess some folks have suggested enlisting 'as', which is a word, of course. -- Keeping medicines from the bloodstreams of the sick; food from the bellies of the hungry; books from the hands of the uneducated; technology from the underdeveloped; and putting advocates of freedom in prisons. Intellectual property is to the 21st century what the slave trade was to the 16th.
On Thu, Nov 12, 2020 at 8:41 PM David Mertz <mertz@gnosis.cx> wrote:
One idea that I cannot recall seeing, but that seems to make sense to me and fit with Python's feel is using a WORD to distinguish between a variable value and a binding target. That is, instead of a special symbol prefixing or suffixing a name, either to indicate it is or is not a binding target. Of course, whether the extra word would be used for binding or for NOT binding is a question still.
I agree 100%. Words instead of sigils is more like the rest of Python. Best, Luciano
NOT_FOUND = 404 match http_code: case 200: print("OK document") case value NOT_FOUND: # use the variable value print("Document not found") case OTHER_CODE: # bind this name print("Other HTTP code", OTHER_CODE)
Of course, this would require a soft keyword, which is a disadvantage. Going the other direction:
NOT_FOUND = 404 match http_code: case 200: print("OK document") case NOT_FOUND: # use the variable value print("Document not found") case bind OTHER_CODE: # bind this name print("Other HTTP code")
To me these read better than the punctuation characters. But I guess some folks have suggested enlisting 'as', which is a word, of course.
-- Keeping medicines from the bloodstreams of the sick; food from the bellies of the hungry; books from the hands of the uneducated; technology from the underdeveloped; and putting advocates of freedom in prisons. Intellectual property is to the 21st century what the slave trade was to the 16th. _______________________________________________ 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/5YUWE7K6... Code of Conduct: http://python.org/psf/codeofconduct/
-- Luciano Ramalho | Author of Fluent Python (O'Reilly, 2015) | http://shop.oreilly.com/product/0636920032519.do | Technical Principal at ThoughtWorks | Twitter: @ramalhoorg
Hello, On Thu, 12 Nov 2020 19:38:38 -0400 David Mertz <mertz@gnosis.cx> wrote: []
One idea that I cannot recall seeing, but that seems to make sense to me and fit with Python's feel is using a WORD to distinguish between a variable value and a binding target. That is, instead of a special
case value NOT_FOUND: # use the variable value print("Document not found")
case bind OTHER_CODE: # bind this name print("Other HTTP code")
To me these read better than the punctuation characters. But I guess some folks have suggested enlisting 'as', which is a word, of course.
This is too verbose, COBOL-style. The whole push is to find concise, yet intuitive and visible "sigils" for one possibility vs another, then see how all 3 options (3rd being what's encoded in PEP634, sigil-less, but with adhoc syntactic constraints) look and feel. [] -- Best regards, Paul mailto:pmiscml@gmail.com
On Fri, 13 Nov 2020 at 09:39, David Mertz <mertz@gnosis.cx> wrote:
I have read a great deal of discussion on the pattern matching PEPs and less formal discussions. It is possible I have overlooked some post in all of that, of course.
... OK, just saw Guido's "wait for new SC" comment, which I suppose applies to this too :-).
One idea that I cannot recall seeing, but that seems to make sense to me and fit with Python's feel is using a WORD to distinguish between a variable value and a binding target. That is, instead of a special symbol prefixing or suffixing a name, either to indicate it is or is not a binding target. Of course, whether the extra word would be used for binding or for NOT binding is a question still.
If someone was prepared to pursue this to the level of writing a 3rd competing PEP, the variant I would personally like to see written up is the one where capture patterns are all prefixed with the keyword `as`. PEP 634 already uses the `PATTERN as NAME` syntax to combine other match patterns with a capture pattern, and I'm going to be amending PEP 642 to propose using `as` when embedding capture patterns inside class patterns (`ATTR as NAME`) and mapping patterns (`KEY as NAME`). From there, it's an entirely plausible step to also require the `as` prefix on capture patterns in sequence patterns and as top level standalone patterns. I personally don't think that extra step would be a good idea due to the inconsistency with name binding and iterable unpacking in regular assignment statements (if I liked the idea, I'd have already included it in PEP 642), but I think "anchor match patterns in normal expressions rather than assignment target syntax" is a credible enough idea that the overall design process would benefit from having a champion write it up.
To me these read better than the punctuation characters. But I guess some folks have suggested enlisting 'as', which is a word, of course.
Indeed, and one that doesn't look too bad for top level patterns: NOT_FOUND = 404 match http_code: case 200: print("OK document") case NOT_FOUND: # use the variable value print("Document not found") case as other_code: # bind this name print("Other HTTP code") It starts to look a bit more strange when matching sequences, though: match seq: case as first, *middle, as last: ... # Or should that be "*as middle"? Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia
On Sat, 14 Nov 2020 at 10:16, Nick Coghlan <ncoghlan@gmail.com> wrote:
On Fri, 13 Nov 2020 at 09:39, David Mertz <mertz@gnosis.cx> wrote:
I have read a great deal of discussion on the pattern matching PEPs and
less formal discussions. It is possible I have overlooked some post in all of that, of course.
... OK, just saw Guido's "wait for new SC" comment, which I suppose
applies to this too :-).
One idea that I cannot recall seeing, but that seems to make sense to me
and fit with Python's feel is using a WORD to distinguish between a variable value and a binding target. That is, instead of a special symbol prefixing or suffixing a name, either to indicate it is or is not a binding target. Of course, whether the extra word would be used for binding or for NOT binding is a question still.
If someone was prepared to pursue this to the level of writing a 3rd competing PEP, the variant I would personally like to see written up is the one where capture patterns are all prefixed with the keyword `as`.
PEP 634 already uses the `PATTERN as NAME` syntax to combine other match patterns with a capture pattern, and I'm going to be amending PEP 642 to propose using `as` when embedding capture patterns inside class patterns (`ATTR as NAME`) and mapping patterns (`KEY as NAME`). From there, it's an entirely plausible step to also require the `as` prefix on capture patterns in sequence patterns and as top level standalone patterns.
I personally don't think that extra step would be a good idea due to the inconsistency with name binding and iterable unpacking in regular assignment statements (if I liked the idea, I'd have already included it in PEP 642), but I think "anchor match patterns in normal expressions rather than assignment target syntax" is a credible enough idea that the overall design process would benefit from having a champion write it up.
To me these read better than the punctuation characters. But I guess some folks have suggested enlisting 'as', which is a word, of course.
Indeed, and one that doesn't look too bad for top level patterns:
NOT_FOUND = 404 match http_code: case 200: print("OK document") case NOT_FOUND: # use the variable value print("Document not found") case as other_code: # bind this name print("Other HTTP code")
It starts to look a bit more strange when matching sequences, though:
match seq: case as first, *middle, as last: ... # Or should that be "*as middle"?
Although the spacing there should probably remain optional, I think that "* as middle" is very straightforward and easy to read.
Cheers, Nick.
-- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia _______________________________________________ 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/LKRWAQX5... Code of Conduct: http://python.org/psf/codeofconduct/
I very much second this opinion /Christian On Sat, 14 Nov 2020, 15.16 Joao S. O. Bueno, <jsbueno@python.org.br> wrote:
On Sat, 14 Nov 2020 at 10:16, Nick Coghlan <ncoghlan@gmail.com> wrote:
On Fri, 13 Nov 2020 at 09:39, David Mertz <mertz@gnosis.cx> wrote:
I have read a great deal of discussion on the pattern matching PEPs and
less formal discussions. It is possible I have overlooked some post in all of that, of course.
... OK, just saw Guido's "wait for new SC" comment, which I suppose
applies to this too :-).
One idea that I cannot recall seeing, but that seems to make sense to
me and fit with Python's feel is using a WORD to distinguish between a variable value and a binding target. That is, instead of a special symbol prefixing or suffixing a name, either to indicate it is or is not a binding target. Of course, whether the extra word would be used for binding or for NOT binding is a question still.
If someone was prepared to pursue this to the level of writing a 3rd competing PEP, the variant I would personally like to see written up is the one where capture patterns are all prefixed with the keyword `as`.
PEP 634 already uses the `PATTERN as NAME` syntax to combine other match patterns with a capture pattern, and I'm going to be amending PEP 642 to propose using `as` when embedding capture patterns inside class patterns (`ATTR as NAME`) and mapping patterns (`KEY as NAME`). From there, it's an entirely plausible step to also require the `as` prefix on capture patterns in sequence patterns and as top level standalone patterns.
I personally don't think that extra step would be a good idea due to the inconsistency with name binding and iterable unpacking in regular assignment statements (if I liked the idea, I'd have already included it in PEP 642), but I think "anchor match patterns in normal expressions rather than assignment target syntax" is a credible enough idea that the overall design process would benefit from having a champion write it up.
To me these read better than the punctuation characters. But I guess some folks have suggested enlisting 'as', which is a word, of course.
Indeed, and one that doesn't look too bad for top level patterns:
NOT_FOUND = 404 match http_code: case 200: print("OK document") case NOT_FOUND: # use the variable value print("Document not found") case as other_code: # bind this name print("Other HTTP code")
It starts to look a bit more strange when matching sequences, though:
match seq: case as first, *middle, as last: ... # Or should that be "*as middle"?
Although the spacing there should probably remain optional, I think that "* as middle" is very straightforward and easy to read.
Cheers, Nick.
-- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia _______________________________________________ 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/LKRWAQX5... Code of Conduct: http://python.org/psf/codeofconduct/
_______________________________________________ Python-Dev mailing list -- python-dev@python.org To unsubscribe send an email to python-dev-leave@python.org https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/GFVLLQVH... Code of Conduct: http://python.org/psf/codeofconduct/
On Sat, Nov 14, 2020 at 11:11:37PM +1000, Nick Coghlan wrote:
On Fri, 13 Nov 2020 at 09:39, David Mertz <mertz@gnosis.cx> wrote:
I have read a great deal of discussion on the pattern matching PEPs and less formal discussions. It is possible I have overlooked some post in all of that, of course.
... OK, just saw Guido's "wait for new SC" comment, which I suppose applies to this too :-).
One idea that I cannot recall seeing, but that seems to make sense to me and fit with Python's feel is using a WORD to distinguish between a variable value and a binding target. That is, instead of a special symbol prefixing or suffixing a name, either to indicate it is or is not a binding target. Of course, whether the extra word would be used for binding or for NOT binding is a question still.
If someone was prepared to pursue this to the level of writing a 3rd competing PEP, the variant I would personally like to see written up is the one where capture patterns are all prefixed with the keyword `as`.
PEP 634 already uses the `PATTERN as NAME` syntax to combine other match patterns with a capture pattern, and I'm going to be amending PEP 642 to propose using `as` when embedding capture patterns inside class patterns (`ATTR as NAME`) and mapping patterns (`KEY as NAME`). From there, it's an entirely plausible step to also require the `as` prefix on capture patterns in sequence patterns and as top level standalone patterns.
I personally don't think that extra step would be a good idea due to the inconsistency with name binding and iterable unpacking in regular assignment statements (if I liked the idea, I'd have already included it in PEP 642), but I think "anchor match patterns in normal expressions rather than assignment target syntax" is a credible enough idea that the overall design process would benefit from having a champion write it up.
To me these read better than the punctuation characters. But I guess some folks have suggested enlisting 'as', which is a word, of course.
Indeed, and one that doesn't look too bad for top level patterns:
NOT_FOUND = 404 match http_code: case 200: print("OK document") case NOT_FOUND: # use the variable value print("Document not found") case as other_code: # bind this name print("Other HTTP code")
It doesn't look too bad because it looks like a switch statement, with only one lonely capture pattern, and an especially simple one at that. (The bound name isn't even used, which strongly suggests that it should be written as the wildcard pattern.) Here is a more representative example, borrowed from here: https://gvanrossum.github.io//docs/PyPatternMatching.pdf match node: case BinOp(Num(left), '+', Num(right)): return Num(left + right) case BinOp(left, '+' | '-', Num(0)): return simplify(left) case UnaryOp('-', UnaryOp('-', item)): return simplify(item) case _: return node which becomes this with the "as" proposal: match node: case BinOp(Num(as left), '+', Num(as right)): return Num(left + right) case BinOp(as left, '+' | '-', Num(0)): return simplify(left) case UnaryOp('-', UnaryOp('-', as item)): return simplify(item) case _: return node Here's another example from the same paper: def create_rectangle(*args, **kwargs): match (args, kwargs): case ([x1, y1, x2, y2], {}) if x2-x1 == y2-y1: return Square(x1, y1, x2-x1) case ([x1, y1, x2, y2], {}): return Rect(x1, y1, x2, y2) case ([(x1, y1), (x2, y2)], {}): return Rect(x1, y1, x2, y2) case ([x, y], {'width': wd, 'height': ht}): return Rect(x, y, x+wd, y+ht) which would become: def create_rectangle(*args, **kwargs): match (args, kwargs): case ([as x1, as y1, as x2, as y2], {}) if x2-x1 == y2-y1: return Square(x1, y1, x2-x1) case ([as x1, as y1, as x2, as y2], {}): return Rect(x1, y1, x2, y2) case ([(as x1, as y1), (as x2, as y2)], {}): return Rect(x1, y1, x2, y2) case ([as x, as y], {'width': as wd, 'height': as ht}): return Rect(x, y, x+wd, y+ht) -- Steve
On Tue, 17 Nov 2020 at 03:52, Steven D'Aprano <steve@pearwood.info> wrote:
Here is a more representative example, borrowed from here:
https://gvanrossum.github.io//docs/PyPatternMatching.pdf
match node: case BinOp(Num(left), '+', Num(right)): return Num(left + right) case BinOp(left, '+' | '-', Num(0)): return simplify(left) case UnaryOp('-', UnaryOp('-', item)): return simplify(item) case _: return node
which becomes this with the "as" proposal:
match node: case BinOp(Num(as left), '+', Num(as right)): return Num(left + right) case BinOp(as left, '+' | '-', Num(0)): return simplify(left) case UnaryOp('-', UnaryOp('-', as item)): return simplify(item) case _: return node
Well, I like the idea to have a keyword instead of a sigil, but `as` does not sounds good in English IMO. For example, in the `with` statement, it's with x as y: [code] I see the pattern matching code and I ask myself: where is the x? PS: pattern matching, for a mere mortal like me, seems to be something very exotical. That's why an explicit, even if verbose, additional keyword seems to me better for reading and understanding the code. For my eyes, it's the same difference between x = y ? z : w and x = y if z else w
On Tue, Nov 17, 2020 at 08:49:28AM +0100, Marco Sulla wrote:
PS: pattern matching, for a mere mortal like me, seems to be something very exotical.
Have you ever written code that looks like this? if isinstance(obj, tuple) and len(obj) ==3: x, y, z = obj elif isinstance(obj, tuple) and len(obj) == 2: x, y = obj z = 0.0 elif isinstance(obj, float): x = obj y = z = 0.0 else: raise ValueError process(x, y, z) That's pattern matching. match obj: case x, y, z: pass case x, y: z = 0.0 case x if isinstance(x, float): y = z = 0.0 case _: raise ValueError process(x, y, z) There may be cleaner or alternative ways to write this as a match statement, I'm still learning pattern matching idioms myself. But in a nutshell, they simplify what would otherwise look like a long, repetitive chain of if, isinstance, sequence unpacking, etc. -- Steve
In Mathematica, you might do this as (roughly): rules = { {x_, y_, z_} :> {x, y, z}, {x_, y_} :> {x, y, 0.0}, x_ :> {x, 0.0, 0.0} } process[Replace[obj, rules]] Whatever you think of the particular syntax: The ability to declare resuable rules seems good. Thinking of replacement functionally seems good. fwiw, Alan Isaac On 11/17/2020 5:02 AM, Steven D'Aprano wrote:
On Tue, Nov 17, 2020 at 08:49:28AM +0100, Marco Sulla wrote:
PS: pattern matching, for a mere mortal like me, seems to be something very exotical.
Have you ever written code that looks like this?
if isinstance(obj, tuple) and len(obj) ==3: x, y, z = obj elif isinstance(obj, tuple) and len(obj) == 2: x, y = obj z = 0.0 elif isinstance(obj, float): x = obj y = z = 0.0 else: raise ValueError process(x, y, z)
That's pattern matching.
match obj: case x, y, z: pass case x, y: z = 0.0 case x if isinstance(x, float): y = z = 0.0 case _: raise ValueError process(x, y, z)
There may be cleaner or alternative ways to write this as a match statement, I'm still learning pattern matching idioms myself. But in a nutshell, they simplify what would otherwise look like a long, repetitive chain of if, isinstance, sequence unpacking, etc.
I'm not sure it matters in all the threads. But my underlying opinion is that we SHOULD have a mechanism to use a plain name (that has an assigned value in the scope) as a value in match patterns, not only as binding targets. However, in contrast to Nick Coghlan, I do not think access should be the default, but that binding should be. I'm convinced by Guido, Brandt, and others that the binding use will be far more common, so adding extra characters for the 90% case does not feel desirable, even if it is arguably more consistent with other elements of the language. The second example I give of binding requiring the extra syntax was for completeness, but I would not support it myself. If binding were to require extra syntax, I think Nick's 'as' suggestion is better than my prefix word idea (if only because it doesn't need a new soft keyword). I do not think the answer of "put the plain name into an enumeration or other object so it can be accessed as a dotted name" is quite enough. Yes, that's possible, but it feels more forced. So in my mind, if I had the choice, it is a decision between a sigil and a word to indicate "no, really use this name as a value!" I like a word better, but none of the current keywords really make sense, so it would need to be a new word. I suggested "value", but another word might be better. On Thu, Nov 12, 2020 at 7:38 PM David Mertz <mertz@gnosis.cx> wrote:
One idea that I cannot recall seeing, but that seems to make sense to me and fit with Python's feel is using a WORD to distinguish between a variable value and a binding target. That is, instead of a special symbol prefixing or suffixing a name, either to indicate it is or is not a binding target. Of course, whether the extra word would be used for binding or for NOT binding is a question still.
NOT_FOUND = 404 match http_code: case 200: print("OK document") case value NOT_FOUND: # use the variable value print("Document not found") case OTHER_CODE: # bind this name print("Other HTTP code", OTHER_CODE)
Of course, this would require a soft keyword, which is a disadvantage. Going the other direction:
NOT_FOUND = 404 match http_code: case 200: print("OK document") case NOT_FOUND: # use the variable value print("Document not found") case bind OTHER_CODE: # bind this name print("Other HTTP code")
To me these read better than the punctuation characters. But I guess some folks have suggested enlisting 'as', which is a word, of course.
-- Keeping medicines from the bloodstreams of the sick; food from the bellies of the hungry; books from the hands of the uneducated; technology from the underdeveloped; and putting advocates of freedom in prisons. Intellectual property is to the 21st century what the slave trade was to the 16th.
-- The dead increasingly dominate and strangle both the living and the not-yet born. Vampiric capital and undead corporate persons abuse the lives and control the thoughts of homo faber. Ideas, once born, become abortifacients against new conceptions.
On Sat, Nov 21, 2020 at 9:52 AM David Mertz <mertz@gnosis.cx> wrote:
So in my mind, if I had the choice, it is a decision between a sigil and a word to indicate "no, really use this name as a value!" I like a word better, but none of the current keywords really make sense, so it would need to be a new word. I suggested "value", but another word might be better.
The good news here is that the PEP 634 syntax is sufficiently restricted that we can always add this later, regardless of whether we end up wanting a sigil or a (soft) keyword, as long as we agree that the meaning of a bare name should be a capture variable. -- --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...>
On Sat, Nov 21, 2020 at 2:47 PM Guido van Rossum <guido@python.org> wrote:
On Sat, Nov 21, 2020 at 9:52 AM David Mertz <mertz@gnosis.cx> wrote:
So in my mind, if I had the choice, it is a decision between a sigil and a word to indicate "no, really use this name as a value!" I like a word better, but none of the current keywords really make sense, so it would need to be a new word. I suggested "value", but another word might be better.
The good news here is that the PEP 634 syntax is sufficiently restricted that we can always add this later, regardless of whether we end up wanting a sigil or a (soft) keyword, as long as we agree that the meaning of a bare name should be a capture variable.
I thought of that. An incremental approach of accepting PEP 634, but (perhaps) adding a soft keyword later is probably the most sensible thing. If the "need the value of a plain name" is a 1% case, a workaround like putting it into an attribute of some object before matching is a minor issue. If that's the 25%+ case, after experience, the argument for some annotation of "use the value" could be added later. -- The dead increasingly dominate and strangle both the living and the not-yet born. Vampiric capital and undead corporate persons abuse the lives and control the thoughts of homo faber. Ideas, once born, become abortifacients against new conceptions.
On 11/21/2020 9:47 AM, David Mertz wrote:
So in my mind, if I had the choice, it is a decision between a sigil and a word to indicate "no, really use this name as a value!" I like a word better, but none of the current keywords really make sense, so it would need to be a new word. I suggested "value", but another word might be better.
NOT_FOUND = 404 match var: case 200: print("OK") case (NOT_FOUND): print("Not Found") case other_code: print("Other code", other_code ) Don't () already indicate an expression to be evaluated? It's only one character longer than the early . suggestion, and already has the desired meaning of "calculated value" not "bound variable".
On 22/11/20 1:07 pm, Henk-Jaap Wagenaar wrote:
On Sat, 21 Nov 2020 at 19:58, Glenn Linderman <v+python@g.nevcal.com <mailto:v%2Bpython@g.nevcal.com>> wrote:
Don't () already indicate an expression to be evaluated?
Does it?
[(a, b)] = [(0, 1)]
Presumably a comma would be needed to match a 1-tuple. case (x): # matches the value of x case (x,): # matches any 1-tuple and binds x -- Greg
On Sat, 21 Nov 2020 at 18:52, David Mertz <mertz@gnosis.cx> wrote:
So in my mind, if I had the choice, it is a decision between a sigil and a word to indicate "no, really use this name as a value!" I like a word better, but none of the current keywords really make sense, so it would need to be a new word. I suggested "value", but another word might be better.
What about `equals`?
On 22/11/20 6:47 am, David Mertz wrote:
I'm convinced by Guido, Brandt, and others that the binding use will be far more common, so adding extra characters for the 90% case does not feel desirable
Minimising the number of characters is not the only consideration. Readability counts too, and I think the proposed DWIM rules suffer in the readability area. There are about five different contexts in which a bare name can appear as part of a match case: * As a constructor name * As a bare name in an argument position * As part of a dotted expression * On the left of an = * On the right of an = Only in some of those contexts is it treated as a name to be assigned. That's a fairly complex bit of mental parsing to do when reading a case. -- Greg
On Sun, 22 Nov 2020 at 01:27, Greg Ewing <greg.ewing@canterbury.ac.nz> wrote:
That's a fairly complex bit of mental parsing to do when reading a case.
I agree, that's why I wrote pattern matching seems exotical to me. I was accustomed by Python to read the code as if it's wrote in simple English. I must admit this is not entirely true for more complex features (generators, async etc), but I feel pattern matching particularly less readable. So any effort to make it more readable is good IMHO. My two cents of a simple programmer. On Sun, 22 Nov 2020 at 01:43, Greg Ewing <greg.ewing@canterbury.ac.nz> wrote:
On 22/11/20 1:07 pm, Henk-Jaap Wagenaar wrote:
On Sat, 21 Nov 2020 at 19:58, Glenn Linderman <v+python@g.nevcal.com <mailto:v%2Bpython@g.nevcal.com>> wrote:
Don't () already indicate an expression to be evaluated?
Does it?
[(a, b)] = [(0, 1)]
Presumably a comma would be needed to match a 1-tuple.
case (x): # matches the value of x
case (x,): # matches any 1-tuple and binds x
I think it could potentially be confused with a programmer style. Parenthesis are optional for tuples. Someone could think it could also write case x: to match the value of x, but actually it binds to x and it will be hard to debug.
On Sun, 22 Nov 2020 at 00:31, Greg Ewing <greg.ewing@canterbury.ac.nz> wrote:
On 22/11/20 6:47 am, David Mertz wrote:
I'm convinced by Guido, Brandt, and others that the binding use will be far more common, so adding extra characters for the 90% case does not feel desirable
Minimising the number of characters is not the only consideration. Readability counts too, and I think the proposed DWIM rules suffer in the readability area.
There are about five different contexts in which a bare name can appear as part of a match case:
* As a constructor name * As a bare name in an argument position * As part of a dotted expression * On the left of an = * On the right of an =
Only in some of those contexts is it treated as a name to be assigned. That's a fairly complex bit of mental parsing to do when reading a case.
Hi Greg, Look at the following (non-pattern-matching) snippet: event = datetime.date(x, month=y, day=z) you have bare names appearing as: * a constructor name (date) * bare name in an argument position (x) * part of a dotted expression (datetime, date) * left of = (event, month, day) * right of = (y, z) some of them are lookups in the namespace (datetime, x, y, z). Others are targets to write (event). "date" is actually a literal to be used as attribute lookup, for reading (a key in the module dictionary). "month" and "day" are literals to lookup in the list of formal parameters of a function, for writing into the new function stack frame. I never found Python students struggle too much with the line above, and I don't expect it to be much different for names in patterns. Names in Python can appear with a lot of different "roles" in a lot of different contexts, but the context is usually easy to recognise (is it left or right of a chain of dots? does it have an = on the left or right? is it in an argument list? a parameter list?). Of course I can never deny if you tell me "I find this syntax hard to read" (only a person can decide what's easy or hard to read for them), but I don't think this "bare names appear in many contexts" is a solid explanation. A hypothesis I have is that many readers of the PEP have been scared of these semantics because they have been laid bare when explaining them in detail, but would never notice in day to day life, in the same way that most Python users would never stop twice to look at the meaning of "a.b.c = 0", even if a semantic description requires us to describe that each of the three names has a different role ("a" is a lookup in the current scopes, "b" is a constant name for the purpose of reading attributes, and "c" is a constant name for the purpose of writing attributes). But looking at the details description of what's going on under the hood is scarier than the intuitive look, and when people read the PEP they are looking under the hood rather than looking at this as users. This is guesswork and could be absolutely wrong, but I hope it helps read this with a different set of eyes.
-- Greg _______________________________________________ Python-Dev mailing list -- python-dev@python.org To unsubscribe send an email to python-dev-leave@python.org https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/LMALNSPB... Code of Conduct: http://python.org/psf/codeofconduct/
On 23/11/20 7:49 am, Daniel Moisset wrote:
Look at the following (non-pattern-matching) snippet:
event = datetime.date(x, month=y, day=z)
The only names that are treated as lvalues there are to the left of an '='. The rules are a lot simpler. One of the Zen lines says "If it's hard to explain, it's probably a bad idea." I think the proposed rules for match cases are objectively harder to explain than those for other expressions, because they're more complicated. -- Greg
Greg Ewing wrote:
On 23/11/20 7:49 am, Daniel Moisset wrote:
Look at the following (non-pattern-matching) snippet: event = datetime.date(x, month=y, day=z)
The only names that are treated as lvalues there are to the left of an '='. The rules are a lot simpler. One of the Zen lines says "If it's hard to explain, it's probably a bad idea." I think the proposed rules for match cases are objectively harder to explain than those for other expressions, because they're more complicated.
I don't believe that it is correct that `month` in `month=y` and `day` in `day=z` in the expression `event = datetime.date(x, month=y, day=z)` are lvalues. They are definitely not assignment targets in the same sense that `event` is an assignment target. `month` and `day` are used to bind the arguments `y` and `z` to the `month` and `day` arguments accepted by the `date` constructor. `event` can be accessed and rebound in the scope that invokes `datetime.date`. However, `month` and `day` are only bound to `y` and `z` in the scope of the body of the `datetime.date` constructor and are not accessible in the scope that invokes `datetime.date`. The behaviour is significantly different.
Hi, Le 23/11/2020 à 01:41, Greg Ewing a écrit :
On 23/11/20 7:49 am, Daniel Moisset wrote:
Look at the following (non-pattern-matching) snippet:
event = datetime.date(x, month=y, day=z)
The only names that are treated as lvalues there are to the left of an '='. […] This is a crucial point for me as well. Especially "month=y" meaning assign from month to y in "case datetime.date(x, month=y, day=z)" still feels really weird, even after reading it times and again in this many-month-old discussion. Sure, people who use pattern matching daily will get used to it, but what about those who only use it once in a while?
I say this as someone who fully appreciates the parallelism between a pattern and the corresponding constructor, and the elegance of this design choice. The rational me likes it, but the instinctive me can't get comfortable with its consequences ;-) If it can be done, replacing the "=" sign with "as" feels like a good compromise: the parallelism is still there, with just enough difference to stand out. Cheers, Baptiste
participants (16)
-
Alan G. Isaac
-
Baptiste Carvello
-
Brian Coleman
-
Christian Nielsen
-
Daniel Moisset
-
David Mertz
-
Glenn Linderman
-
Greg Ewing
-
Guido van Rossum
-
Henk-Jaap Wagenaar
-
Joao S. O. Bueno
-
Luciano Ramalho
-
Marco Sulla
-
Nick Coghlan
-
Paul Sokolovsky
-
Steven D'Aprano