[Python-Dev] Re: PEP 622 version 2 (Structural Pattern Matching)
Hello everyone,
I'm sorry if my proposition has already being said, or even withdrawn,
but I think that capture variables shouldn't be as implicit as they
are now. I didn't see any mention of capture variable patterns in
the rejected ideas. So here is my idea:
I've looked at the PEP very quickly, jumping on the examples to have
a taste and an idea of what was going here. I saw a new kind of control
structure based on structural pattern matching (pattern based on
classes or compositions of classes to make it short). A very good
idea, emphasized by Tobias Kohn ("Another take on PEP 622") is that
pattern matching eases the writting of code based on matching such
structures, and that capturing values stored inside of these
structures at the match time really eases the writting of the code
associated with this match.
But... looking at the examples, it wasn't very obvious that some
variables were catching variables and some others were matching ones.
I then read in details some rules about how to discover what is a
captured variable. But I'm not sure everybody will do this...
Zen of Python tells us that "explicit is better than implicit". I know
this is not a rule written in the stone, but I think here, it applies
very well.
Guido said :
> We’re really looking
> for a solution that tells you when you’re looking at an individual
> case which variables are captured and which are used for
> load-and-compare.
>
> Marking up the capture variables with some sigil (e.g. $x or
> x?)
> or other markup (e.g. backticks or ) makes this common case ugly
> and inconsistent: it’s unpleasant to see for example
>
> case %x, %y:
> print(x, y)
Guido talk about a "sigil", which seems to be a meaningless mark only
here to help the parser understand what the dev was writing.
I propose that this "sigil" be the affectation mark : "=". Look :
z = 42
match pt:
case x=, y=, z:
print(x, y, "z == 42")
Or this one :
def make_point_3d(pt):
match pt:
case (x=, y=):
return Point3d(x, y, 0)
case (x=, y=, z=):
return Point3d(x, y, z)
case Point2d(x=, y=):
return Point3d(x, y, 0)
case Point3d(_, _, _):
return pt
case _:
raise TypeError("not a point we support")
On the need to be explicit:
Simple case blocks will perhaps be a bit longer to write, but will
not be harder to read, since they stay in the "simple case blocks"
family.
More complex cases will be harder to write, but the explicit markup
will help understand what will be captured and where, and what will
be looked-and-matched, using already known rules : looked-and-matched
expressions will be computed as usual, then compared with the match
term, and captured expression will be computed to a l-value (which
is much more restrictive than random expressions).
Moreover, explicilty introducing a difference between "capture" and
"look-and-match" will help newcomers to understand what is the point
about a match without they have to look at a PEP or other normative
document.
Remember that code has to be readable, because it will be read much
more often than written. The reader has to understand quickly but not
in details what will happen. Being explicit removes they the task
to concentrate on this point.
Also remember that Python has to be teached, and that all that is
implicit in the code have to be explicited when teaching. And the
longer you teach microdetails like what is the difference between
"capture" vs "look-and-match", the less your audience will be prone
to listen to you.
On the drawback to be explicit:
Adding a mark to every captured variables can and will be annoying.
More annoying than not adding it. It's obvious. But we don't expect to
have more than a handful of captured variables per case. Or the case
is perhaps too complex, not to say perhaps too complicated.
Using a carrefully choosen mark can alleviate this drawback. Using
an already accepted and commonly used symbol will surely help.
I know that Python will diverge from other languages on this point. Yes,
but Python already diverged from others languages, and it is see
by the community that it is for the better. Ex : the conditional expression
aka the "ternary operator" aka "x = blabla if plop else bla".
And I'll be a bit confused to have to explain that "captured variables"
look like simple expressions "but are not" because that's how things
are written in other functionnal languages. I'm not sure it will
convince anybody that aren't already familiar with pattern matching in
functionnal languages (which is a big topic by itself).
On the syntax:
Using the "=" character is well know, easy to find on a keyboard
and already hold the semantics of "putting a value in a variable".
So this mark is not a random sigil, but the way we write
affectations, with a l-value, a "=" character, and a
r-value. The r-value is given
[Python-Dev] PEP 626: Precise line numbers for debugging and other tools.
Hi all, I'd like to announce a new PEP. It is mainly codifying that Python should do what you probably already thought it did :) Should be uncontroversial, but all comments are welcome. Cheers, Mark. ___ Python-Dev mailing list -- [email protected] To unsubscribe send an email to [email protected] https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/[email protected]/message/BMX32UARJFY3PZZYKRANS6RCMR2XBVVM/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] Re: PEP 622 version 2 (Structural Pattern Matching)
On Fri, 17 Jul 2020 at 12:26, wrote:
> Hello everyone,
>
> I'm sorry if my proposition has already being said, or even withdrawn,
> but I think that capture variables shouldn't be as implicit as they
> are now. I didn't see any mention of capture variable patterns in
> the rejected ideas. So here is my idea:
>
> I've looked at the PEP very quickly, jumping on the examples to have
> a taste and an idea of what was going here. I saw a new kind of control
> structure based on structural pattern matching (pattern based on
> classes or compositions of classes to make it short). A very good
> idea, emphasized by Tobias Kohn ("Another take on PEP 622") is that
> pattern matching eases the writting of code based on matching such
> structures, and that capturing values stored inside of these
> structures at the match time really eases the writting of the code
> associated with this match.
>
> But... looking at the examples, it wasn't very obvious that some
> variables were catching variables and some others were matching ones.
> I then read in details some rules about how to discover what is a
> captured variable. But I'm not sure everybody will do this...
>
> Zen of Python tells us that "explicit is better than implicit". I know
> this is not a rule written in the stone, but I think here, it applies
> very well.
>
> Guido said :
> > We’re really looking
> > for a solution that tells you when you’re looking at an individual
> > case which variables are captured and which are used for
> > load-and-compare.
> >
> > Marking up the capture variables with some sigil (e.g. $x or
> > x?)
> > or other markup (e.g. backticks or ) makes this common case ugly
> > and inconsistent: it’s unpleasant to see for example
> >
> > case %x, %y:
> > print(x, y)
>
> Guido talk about a "sigil", which seems to be a meaningless mark only
> here to help the parser understand what the dev was writing.
>
> I propose that this "sigil" be the affectation mark : "=". Look :
>
> z = 42
> match pt:
> case x=, y=, z:
> print(x, y, "z == 42")
>
> Or this one :
>
> def make_point_3d(pt):
> match pt:
> case (x=, y=):
> return Point3d(x, y, 0)
> case (x=, y=, z=):
> return Point3d(x, y, z)
> case Point2d(x=, y=):
> return Point3d(x, y, 0)
> case Point3d(_, _, _):
> return pt
> case _:
> raise TypeError("not a point we support")
>
>
I kind of agree it is nicer to be more explicit. But somehow x= looks
ugly. It occurred to me (and, again, apologies if already been mentioned),
we might use the `as` keyword here.
The example above would become:
def make_point_3d(pt):
match pt:
case (as x, as y):
return Point3d(x, y, 0)
case (as x, as y, as z):
return Point3d(x, y, z)
case Point2d(as x, as y):
return Point3d(x, y, 0)
case Point3d(_, _, _):
return pt
case _:
raise TypeError("not a point we support")
If having "as x" as a standalone expression without anything to the left of
"as" causes confusion, we could instead mandate the use of _ thus:
case (_ as x, _ as y):
return Point3d(x, y, 0)
On the need to be explicit:
>
> Simple case blocks will perhaps be a bit longer to write, but will
> not be harder to read, since they stay in the "simple case blocks"
> family.
>
> More complex cases will be harder to write, but the explicit markup
> will help understand what will be captured and where, and what will
> be looked-and-matched, using already known rules : looked-and-matched
> expressions will be computed as usual, then compared with the match
> term, and captured expression will be computed to a l-value (which
> is much more restrictive than random expressions).
>
> Moreover, explicilty introducing a difference between "capture" and
> "look-and-match" will help newcomers to understand what is the point
> about a match without they have to look at a PEP or other normative
> document.
>
> Remember that code has to be readable, because it will be read much
> more often than written. The reader has to understand quickly but not
> in details what will happen. Being explicit removes they the task
> to concentrate on this point.
>
> Also remember that Python has to be teached, and that all that is
> implicit in the code have to be explicited when teaching. And the
> longer you teach microdetails like what is the difference between
> "capture" vs "look-and-match", the less your audience will be prone
> to listen to you.
>
> On the drawback to be explicit:
>
> Adding a mark to every captured variables can and will be annoying.
> More annoying than not adding it. It's obvious. But we don't expect to
> have more than a handful of captured variables per case. Or the case
> is perhaps too complex, not
[Python-Dev] Re: PEP 626: Precise line numbers for debugging and other tools.
https://www.python.org/dev/peps/pep-0626/ :) --Ned. On 7/17/20 10:48 AM, Mark Shannon wrote: Hi all, I'd like to announce a new PEP. It is mainly codifying that Python should do what you probably already thought it did :) Should be uncontroversial, but all comments are welcome. Cheers, Mark. ___ Python-Dev mailing list -- [email protected] To unsubscribe send an email to [email protected] https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/[email protected]/message/BMX32UARJFY3PZZYKRANS6RCMR2XBVVM/ Code of Conduct: http://python.org/psf/codeofconduct/ ___ Python-Dev mailing list -- [email protected] To unsubscribe send an email to [email protected] https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/[email protected]/message/SC5TWSCODSUZRMGNCXBBCV7AOS2LM2FO/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] Re: PEP 626: Precise line numbers for debugging and other tools.
PEP 626 wrote: Abstract Python should guarantee that when tracing is turned on, "line" tracing events are generated for all lines of code executed and only for lines of code that are executed. The sample code shows `return` events being executed, even when there is no `return` line -- doesn't this contradict the "only for lines of code executed"? Maybe the Tracing section should have an entry for multiple line events from the same line. A side effect of ensuring correct line numbers, is that some bytecodes will need to be marked as artificial, and not have a meaningful line number. Do you have an example of this? -- ~Ethan~ ___ Python-Dev mailing list -- [email protected] To unsubscribe send an email to [email protected] https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/[email protected]/message/6NUA4OHJDERI77A2DUEF57NNBRIADHBC/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] Re: PEP 622 version 2 (Structural Pattern Matching)
On 7/17/20 8:26 AM, Gustavo Carneiro wrote: I kind of agree it is nicer to be more explicit. But somehow x= looks ugly. It occurred to me (and, again, apologies if already been mentioned), we might use the `as` keyword here. The problem with any kind of sigil/keyword is that it becomes line noise -- we would have to train ourselves to ignore them in order to see the structure and variables we are actually interested in. Once we become adept at ignoring them, we will again have difficulties when debugging as we won't easily see them. Besides which, the problem is solved: - namespace.var is a lookup - var is a store -- ~Ethan~ ___ Python-Dev mailing list -- [email protected] To unsubscribe send an email to [email protected] https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/[email protected]/message/TUQMGYFL4PDEP2VVTRNHDQHQLQ4ELZ4Y/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] PEP 622: capturing into an explicit namespace
Hi Python-dev and PEP 622 Authors, I saw this idea, or something like it, posted by a couple of people, but didn't see much discussion of it, and skimming the PEP today, I didn't see a mention of it. Maybe I just missed it; my apologies if so, and a link to the relevant discussion/text would be appreciated. In any case, the basic idea was to have an explicit namespace that captures are put into, and is treated as assignment instead of lookup. e.g. match get_point() into m: case Point(m.x, m.y): print(m.x, m.y) ...etc... A variation I saw was "as" instead of "into"; the particular token is bikeshedding. The core idea is an explicit name that is "special" within the match's case expressions. Personally, I thought this was a rather elegant solution to the load-vs-store problem for names. This is because, essentially, it changes the mental model from "some non-dotted names are special, some aren't, keep a careful eye out" to "only "m." is special, everything else is regular". I haven't thought about this too deeply (analysis tools might benefit, too?); I wanted to keep this initial email short before investing time/energy/thought into it in case it had already been discussed and discarded. ___ Python-Dev mailing list -- [email protected] To unsubscribe send an email to [email protected] https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/[email protected]/message/U3T3724GBBWDHEXYGIGRFJFQWBQLT35F/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] Re: PEP 626: Precise line numbers for debugging and other tools.
PEP 626: Rather than attempt to fix the co_lnotab attribute, a new method co_lines() will be added, which returns an iterator over bytecode offsets and source code lines. Why not attempt to fix co_lnotab? -- ~Ethan~ ___ Python-Dev mailing list -- [email protected] To unsubscribe send an email to [email protected] https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/[email protected]/message/JV77JETAIAXSGE6MTXTHXLCNH5OEAF5R/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] Re: PEP 626: Precise line numbers for debugging and other tools.
I like the proposal in general but I am against removing lnotab. The reason is that many tools rely on reading this attribute to figure out the Python call stack information. For instance, many sampler profilers read this memory by using ptrace or process_vm_readv and they cannot execute any code on the process under tracing as that would be a security issue. If we remove a 'static' view of that information, it will impact negatively the current set of remote process analysis tools. The proposed new way of retrieving the line number will rely (if we deprecate and remove lnotab) on executing code, making it much more difficult for the ecosystem of profilers and remote process analysis tools to do their job. -- Pablo On Fri, 17 Jul 2020, 15:55 Mark Shannon, wrote: > Hi all, > > I'd like to announce a new PEP. > > It is mainly codifying that Python should do what you probably already > thought it did :) > > Should be uncontroversial, but all comments are welcome. > > Cheers, > Mark. > ___ > Python-Dev mailing list -- [email protected] > To unsubscribe send an email to [email protected] > https://mail.python.org/mailman3/lists/python-dev.python.org/ > Message archived at > https://mail.python.org/archives/list/[email protected]/message/BMX32UARJFY3PZZYKRANS6RCMR2XBVVM/ > Code of Conduct: http://python.org/psf/codeofconduct/ > ___ Python-Dev mailing list -- [email protected] To unsubscribe send an email to [email protected] https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/[email protected]/message/57OXMUBV5FAEFXULRBCRAHEF7Q5GP6QT/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] Summary of Python tracker Issues
ACTIVITY SUMMARY (2020-07-10 - 2020-07-17) Python tracker at https://bugs.python.org/ To view or respond to any of the issues listed below, click on the issue. Do NOT respond to this message. Issues counts and deltas: open7550 (+20) closed 45517 (+35) total 53067 (+55) Open issues with patches: 3067 Issues opened (39) == #39960: Using typename.__setattr__ in extension type with Py_TPFLAGS_H https://bugs.python.org/issue39960 reopened by gvanrossum #41271: Add support for io_uring to cpython https://bugs.python.org/issue41271 opened by cooperlees #41272: New clause in FOR and WHILE instead of ELSE https://bugs.python.org/issue41272 opened by catrudis #41273: asyncio: proactor read transport: use recv_into instead of rec https://bugs.python.org/issue41273 opened by tontinton #41275: Clarify whether Futures can be awaited multiple times https://bugs.python.org/issue41275 opened by JustAnotherArchivist #41277: documentation: os.setxattr() errno EEXIST and ENODATA https://bugs.python.org/issue41277 opened by w0rthle$$ #41278: IDLE: Clarify some completion details in doc https://bugs.python.org/issue41278 opened by Alex-Python-Programmer #41279: Convert StreamReaderProtocol to a BufferedProtocol https://bugs.python.org/issue41279 opened by tontinton #41281: Wrong/missing code formats in datetime documentation https://bugs.python.org/issue41281 opened by yyyan #41282: Deprecate and remove distutils https://bugs.python.org/issue41282 opened by jaraco #41283: The parameter name for imghdr.what in the documentation is wro https://bugs.python.org/issue41283 opened by aeltawela #41287: __doc__ attribute is not set in property-derived classes https://bugs.python.org/issue41287 opened by Sergei Izmailov #41292: Dead link in Windows FAQ https://bugs.python.org/issue41292 opened by Michel Samia #41293: fix confusing example in hashlib docs https://bugs.python.org/issue41293 opened by Pavel Trukhanov #41294: Allow '__qualname__' to be an instance of 'DynamicClassAttribu https://bugs.python.org/issue41294 opened by WildCard65 #41295: CPython 3.8.4 regression on __setattr__ in multiinheritance wi https://bugs.python.org/issue41295 opened by kam193 #41297: Remove doctest import from heapq https://bugs.python.org/issue41297 opened by alexchandel #41298: Enable handling logoff and shutdown Windows console events https://bugs.python.org/issue41298 opened by eryksun #41299: Python3 threading.Event().wait time is twice as large as Pytho https://bugs.python.org/issue41299 opened by SD #41300: IDLE: add missing import io in iomenu.py https://bugs.python.org/issue41300 opened by nirinA raseliarison #41303: perf_counter result does not count system sleep time in Mac OS https://bugs.python.org/issue41303 opened by nooB #41305: Add StreamReader.readinto() https://bugs.python.org/issue41305 opened by tontinton #41306: test_tk test_widgets.ScaleTest fails with Tk 8.6.10 https://bugs.python.org/issue41306 opened by felixonmars #41307: "email.message.Message.as_bytes": fails to correctly handle " https://bugs.python.org/issue41307 opened by dmaurer #41308: socket.connect() slow to time out on Windows https://bugs.python.org/issue41308 opened by steve.dower #41309: test_subprocess.test_pause_reading timing out randomly on Wind https://bugs.python.org/issue41309 opened by steve.dower #41310: micro-optimization: increase our float parsing speed by Nx https://bugs.python.org/issue41310 opened by gregory.p.smith #41311: Add a function to get a random sample from an iterable (reserv https://bugs.python.org/issue41311 opened by oscarbenjamin #41314: __future__ doc and PEP 563 conflict https://bugs.python.org/issue41314 opened by wyz23x2 #41315: Add mathematical functions as wrappers to decimal.Decimal meth https://bugs.python.org/issue41315 opened by Jean Abou Samra #41316: tarfile: Do not write full path in FNAME field https://bugs.python.org/issue41316 opened by ArtemSBulgakov #41317: sock_accept() does not remove server socket reader on cancella https://bugs.python.org/issue41317 opened by alex.gronholm #41318: Better error message of "Cannot recover from stack overflow." https://bugs.python.org/issue41318 opened by th #41320: async process closing after event loop closed https://bugs.python.org/issue41320 opened by kcwu #41321: Calculate timestamp is wrong in datetime.datetime https://bugs.python.org/issue41321 opened by dh4931 #41322: unittest: Generator test methods will always be marked as pass https://bugs.python.org/issue41322 opened by defreng #41323: Perform "peephole" optimization directly on control-flow graph https://bugs.python.org/issue41323 opened by Mark.Shannon #41324: Add a minimal decimal capsule API https://bugs.python.org/issue41324 opened by skrah #41325: Document addition of `mock.call_args.args` and `mock.call_args https://bugs.python.org/issue41325 opened by uspike Most recent 15 issues with no rep
[Python-Dev] Re: PEP 622 version 2 (Structural Pattern Matching)
I've built the reference implementation and I'm experimenting with the
new syntax in the edgedb codebase. It seems to have plenty of places
where pattern matching adds clarity. I'll see if I find particularly
interesting examples of that to share.
So far I'm +1 on the proposal, and I like the second iteration of it.
Except that I'm really sad to see the __match__ protocol gone.
Quoting the PEP:
> One drawback of this protocol is that the arguments to __match__ would be
> expensive to construct, and could not be pre-computed due to the fact that,
> because of the way names are bound, there are no real constants in Python.
While it's not possible to precompute the arguments ahead of time, it
certainly should be possible to cache them similarly to how I
implemented global names lookup cache in CPython. That should
alleviate this particular performance consideration entirely.
Having __match__ would allow some really interesting use cases. For
example, for binary protocol parsers it would be possible to replicate
erlang approach, e.g.:
match buffer:
case Frame(char('X'), len := UInt32(), flags := Bits(0, 1, flag1,
flag2, 1, 1))
would match a Frame of message type 'X', capture its length, and
extract two bit flags. This perhaps isn't the greatest example of how
a full matching protocol could be used, but it's something that I
personally wanted to implement.
Yury
___
Python-Dev mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at
https://mail.python.org/archives/list/[email protected]/message/SCJ6H6KAE2WNHIVOEQ7M5YCZMU4HCYN6/
Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] Re: PEP 622: Structural Pattern Matching (version 2)
Mark Shannon wrote: > In future, could you avoid editing emails when replying to them? > A lot of context can get lost. I'll add another voice to Ethan's saying that I appreciate having as much as possible trimmed. As long as people are arguing in good faith (and I assume that they are here), the loss of context is usually pretty small, and outweighed by being able to find the newly important part more quickly. (I say this as someone reading and replying through the archives, in a way that seems to mangle quoted portions -- but they are usually still good enough to be useful.) > ... Yes, the pattern matching syntax is more concise in some > circumstances, but there still needs to be justification why a > combination of simpler language changes is insufficient. Code that fits on a single small (24x80) screen (without getting too dense) is much easier to understand, because I can see it all at once, instead of needing to remember things while I flip back and forth. A combination of simpler changes might be fine, but shorter really is very valuable, all by itself. > Saves two lines of code, but introduces two bugs! > (Assuming that the original behavior should be preserved) That is a pretty big assumption. I'm guessing that at least one of the "bugs" is that sequences other than the built-in list and tuple are now also accepted. Maybe there are good reasons to exclude other sequences, but ... in my experience, the reason is usually that someone didn't think of it, and no one felt strongly enough to fix it yet. That would mean pattern matching led to a bug *fix*. Closed source code tends to be even more fragile, though it also tends to not see as many surprising input types in the first place. > If you don't have access to the original source, then it can be made a > function, not a method. Even when I have read access, I may not have write access. Creating and naming a separate match function every place I need to match isn't quite boilerplate, but it adds enough code to feel that way. Trying to use a single match function with parameters gets ugly in a different way. I'm not quite convinced that this PEP has found the magic solution, but the goal is clearly worthy. > On 14/07/2020 5:25 pm, Tobias Kohn wrote: > > match response.status: > > case HTTP_RESPONSE.UPGRADE_REQUIRED: > Are you suggesting that all constants live in a separate module? The limit to dotted names is a possibly temporary wart. But even with that restriction, there is no reason you can't gather constants on an object first, and use its attributes. > For a PEP to succeed it needs to show ... > That the proposed change is the best known solution for the > problem being addressed. I think the bigger barrier is "although never is often better than right now," and hope that a better solution will be found later, and fear that backwards compatibility with this would block that better solution. (To be very explicit, I personally abstain on this, because I am not sure whether this is "good enough", nor am I confident a better solution can ever be found.) > I worry that the PEP is treating pattern matching as an ideal which we > should be striving towards. That is a bad thing, IMO. Fair. Like annotations as a typing system, you can personally ignore it if it isn't helpful, but there is still some ecosystem cost. I would like to see more old/new comparisons to judge how intrusive this will be, but eventually there will be (or not be) a leap of faith. In the past, most of those have worked out. > Pattern matching is well suited to statically typed functional languages. and statically typed data domains and communications protocols -jJ ___ Python-Dev mailing list -- [email protected] To unsubscribe send an email to [email protected] https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/[email protected]/message/4S75QY4FVVXW7YGTSFRHEXBK5OXXJM6Y/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] Re: PEP 622 version 2 (Structural Pattern Matching)
On Fri, Jul 17, 2020 at 1:45 PM Yury Selivanov
wrote:
> I've built the reference implementation and I'm experimenting with the
> new syntax in the edgedb codebase. It seems to have plenty of places
> where pattern matching adds clarity. I'll see if I find particularly
> interesting examples of that to share.
>
> So far I'm +1 on the proposal, and I like the second iteration of it.
> Except that I'm really sad to see the __match__ protocol gone.
>
It will be back, just not in 3.10. We need more experience with how
match/case are actually used to design the right `__match__` protocol.
> Quoting the PEP:
>
> > One drawback of this protocol is that the arguments to __match__ would
> be expensive to construct, and could not be pre-computed due to the fact
> that, because of the way names are bound, there are no real constants in
> Python.
>
Note: That's not referring to the `__match__` protocol from version 1 of
the PEP, but to a hypothetical (and IMO sub-optimal) `__match__` protocol
that was discussed among the authors prior to settling on the protocol from
version 1.
> While it's not possible to precompute the arguments ahead of time, it
> certainly should be possible to cache them similarly to how I
> implemented global names lookup cache in CPython. That should
> alleviate this particular performance consideration entirely.
>
Where's that global names lookup cache? I seem to have missed its
introduction. (Unless you meant PEP 567?)
> Having __match__ would allow some really interesting use cases. For
> example, for binary protocol parsers it would be possible to replicate
> erlang approach, e.g.:
>
> match buffer:
> case Frame(char('X'), len := UInt32(), flags := Bits(0, 1, flag1,
> flag2, 1, 1))
>
> would match a Frame of message type 'X', capture its length, and
> extract two bit flags. This perhaps isn't the greatest example of how
> a full matching protocol could be used, but it's something that I
> personally wanted to implement.
>
I see, you'd want the *types* of the arguments to be passed into
`Frame.__match__`. That's interesting, although I have a feeling that if I
had a real use case like this I'd probably be able to come up with a better
DSL for specifying messages than this.
--
--Guido van Rossum (python.org/~guido)
*Pronouns: he/him **(why is my pronoun here?)*
___
Python-Dev mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at
https://mail.python.org/archives/list/[email protected]/message/AHO3SMUGTAUJUDDC5CTB66WYZBXX7UQJ/
Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] Re: PEP 622: capturing into an explicit namespace
On 18/07/20 4:34 am, Richard Levasseur wrote: match get_point() into m: case Point(m.x, m.y): print(m.x, m.y) ...etc... Personally, I thought this was a rather elegant solution to the load-vs-store problem for names. This is because, essentially, it changes the mental model from "some non-dotted names are special, some aren't, keep a careful eye out" to "only "m." is special, everything else is regular". This is a variant of "mark the assignments, not the values", but with the marking done in a somewhat subtle way that can potentially change from one match statement to another. I have trouble seeing this as an improvement over just picking a character to use for the marking. -- Greg ___ Python-Dev mailing list -- [email protected] To unsubscribe send an email to [email protected] https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/[email protected]/message/G2LOCBWEKHRH3PCUXDQFOBRJIZCVPTYW/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] Re: Another take on PEP 622
On 7/16/2020 9:51 PM, Tobias Kohn wrote: Hi Everyone, I feel there are still quite a few misconceptions around concerning PEP 622 and the new pattern matching feature it proposes. Please allow me therefore to take another attempt at explaining the ideas behind PEP 622 with a different approach. Bear in mind that I naturally cannot cover everything, though, and that some parts presented here are still slightly simplified. Thank you Tobias. I am a fan of looking at things from multiple viewpoint. For 200 years, physicists argued about whether light is waves or particles, before discovering that 'neither' and 'both' were more correct. 1. Function Overloading 2. Visitor Pattern and Dispatch > 3. Shape and Structure [snip, snip, snip] In an assignment statement, the code to the left of '=' is a 'target list' of 'target's, with some idiosyncratic rules. Even though it might, misleadingly, be called a 'target expression', it is not an expression to be evaluated. Similarly, the code between parentheses in a def statement is a 'parameter list' of 'defparameter' and special symbols, with other idiosyncratic rules. Both could be called 'binding lists' or more generally, 'binding structures'. To me, the important point of your point is that 'case' is somewhat analogous to 'def', and that the stuff between 'case' and ':' is a binding structure. We should call this structure a 'match structure'. It is misleading and confusing to call it a 'match expression'. A match structure consists of a 'match list' of 'match items' or 'matcher's and an optional "'if' ". Matchers have a 3rd, new, and larger set of idiosyncratic rules. The optional condition is an escape hatch for when expressing the intended match constraint and corresponding match set is difficult or worse using the match rules. As with target and parameter items, untagged simple name matchers are (and I now see, should be) binding targets. (The parameter list tags are ':' for types and '=' for default values.) Unlike assignment targets, dotted names and subscriptings are not binding targets. Like parameter lists, match lists include literals. Match lists also include syntactic structure not seen in the other binding structures. -- Terry Jan Reedy ___ Python-Dev mailing list -- [email protected] To unsubscribe send an email to [email protected] https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/[email protected]/message/NNZ67OMAV2CDV7GSX64SOLUAERJSF5HP/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] Re: PEP 622 idea: "match case object" to represent match patterns
On Thu, Jul 16, 2020 at 9:21 AM Federico Salerno
wrote:
> [...]
Now consider the following refactor:
>
> 3d_point = MatchCase("Point(x, y, z)")
> other_3d_point = MatchCase("Point(_, _, _)")
> point_with_my_y = MatchCase("Point(_, {})", my_y) # syntax with {} is
> debatable.
> other_2d_point = MatchCase("Point(_, y)")
>
> match some_point:
> case 3d_point if 3d_point[0] > 3d_point[1]:
> # 3d_point exposes x, y, and zwith the names given
> # in the declaration, as well as numerically,
> # through __getitem__ or perhaps also through attributes
> # like .args and .kwargs.
> ...
> case other_3d_point:
> # other_3d_point[0] through [2] are available, while
> # other_3d_point["_"] == other_3d_point[2] because it's the last
> # one that was given. Presumably the programmer wouldn't care
> about it.
> ...
> case point_with_my_y as pt:
> # pt still exposes positional arguments like pt[0], pt[1] or
> pt.args
> # as well as pt["_"] (== pt[0] in this case), but pt[1] has no
> # equivalent in pt.kwargs because no name was given.
> ...
> case Point(10, _):
> # Python would construct its own MatchCase here and behave as
> expected.
> ...
> case other_2d_point:
> print(f"Bidimensional point with y={other_2d_point['y']}.")
> case _:
> ...
>
During our internal discussions (before we published the first draft) I
briefly proposed a similar idea. But it was quickly pointed out by my
co-authors that this doesn't fly, because when the parser sees `case
other_3d_point:` it doesn't know whether you meant this as a capture
pattern (binding the variable `other_3d_point`) or as a pattern object.
Also with your proposal the compiler would not be able to tell that x, y
and z are local variables, because they are only mentioned inside string
literals.
Another way to look at it: if you have some common assignment target, say:
```
x, y, z = point1
x, y, z = point2
x, y, z = point3
```
you can't define an object that serves as a shortcut for the `x, y, z`
assignment target -- this (obviously!) does not work:
```
xyz = AssignmentTarget("x, y, z")
xyz = point1
xyz = point2
xyz = point3
```
(You could construct similarly absurd examples for function signatures.)
Patterns are more like assignment targets or function signatures than like
expressions, so we shouldn't be surprised that we can't define objects to
serve as shortcuts here. It could probably be done with a suitable macro
preprocessing feature, but that's a much larger discussion (that I'm
definitely not going to tackle).
--
--Guido van Rossum (python.org/~guido)
*Pronouns: he/him **(why is my pronoun here?)*
___
Python-Dev mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at
https://mail.python.org/archives/list/[email protected]/message/BLD536S36IKFTI7SXRE3VPYT7KOFP5PR/
Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] Re: PEP 622 version 2 (Structural Pattern Matching)
On Fri, Jul 17, 2020 at 3:54 PM Guido van Rossum wrote:
>
> On Fri, Jul 17, 2020 at 1:45 PM Yury Selivanov
> wrote:
>>
>> I've built the reference implementation and I'm experimenting with the
>> new syntax in the edgedb codebase. It seems to have plenty of places
>> where pattern matching adds clarity. I'll see if I find particularly
>> interesting examples of that to share.
>>
>> So far I'm +1 on the proposal, and I like the second iteration of it.
>> Except that I'm really sad to see the __match__ protocol gone.
>
>
> It will be back, just not in 3.10. We need more experience with how
> match/case are actually used to design the right `__match__` protocol.
Makes sense.
>
>>
>> Quoting the PEP:
>>
>> > One drawback of this protocol is that the arguments to __match__ would be
>> > expensive to construct, and could not be pre-computed due to the fact
>> > that, because of the way names are bound, there are no real constants in
>> > Python.
>
>
> Note: That's not referring to the `__match__` protocol from version 1 of the
> PEP, but to a hypothetical (and IMO sub-optimal) `__match__` protocol that
> was discussed among the authors prior to settling on the protocol from
> version 1.
>
>>
>> While it's not possible to precompute the arguments ahead of time, it
>> certainly should be possible to cache them similarly to how I
>> implemented global names lookup cache in CPython. That should
>> alleviate this particular performance consideration entirely.
>
>
> Where's that global names lookup cache? I seem to have missed its
> introduction. (Unless you meant PEP 567?)
Here are the related bpos of where Inada-san and I worked on this:
https://bugs.python.org/issue28158
https://bugs.python.org/issue26219
>
>>
>> Having __match__ would allow some really interesting use cases. For
>> example, for binary protocol parsers it would be possible to replicate
>> erlang approach, e.g.:
>>
>> match buffer:
>> case Frame(char('X'), len := UInt32(), flags := Bits(0, 1, flag1,
>> flag2, 1, 1))
>>
>> would match a Frame of message type 'X', capture its length, and
>> extract two bit flags. This perhaps isn't the greatest example of how
>> a full matching protocol could be used, but it's something that I
>> personally wanted to implement.
>
>
> I see, you'd want the *types* of the arguments to be passed into
> `Frame.__match__`. That's interesting, although I have a feeling that if I
> had a real use case like this I'd probably be able to come up with a better
> DSL for specifying messages than this.
Yeah, it's an open question if this is a good idea or not. FWIW here's
a relevant quick erlang tutorial:
https://dev.to/l1x/matching-binary-patterns-11kh that shows what it
looks like in erlang (albeit the syntax is completely alien to
Python).
Yury
___
Python-Dev mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at
https://mail.python.org/archives/list/[email protected]/message/LMWGQX4RNZE2WS34OM6QU7SLFVQIKYT3/
Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] Re: PEP 622 version 2 (Structural Pattern Matching)
On 7/17/2020 7:23 AM, [email protected] wrote: Hello everyone, I'm sorry if my proposition has already being said, or even withdrawn, but I think that capture variables shouldn't be as implicit as they are now. I've looked at the PEP very quickly, jumping on the examples to have a taste and an idea of what was going here. I saw a new kind of control structure based on structural pattern matching (pattern based on classes or compositions of classes to make it short). A very good idea, emphasized by Tobias Kohn ("Another take on PEP 622") is that pattern matching eases the writting of code based on matching such structures, and that capturing values stored inside of these structures at the match time really eases the writting of the code associated with this match. A major points of Kohn's post is that 'case' is analogous to 'def' and match lists are analogous to parameter lists. In parameter lists, untagged simple names ('parameter names') are binding targets. Therefore, untagged simple names in match lists, let us call them 'match names' should be also. I elaborated on this in my response to Tobias. -- Terry Jan Reedy ___ Python-Dev mailing list -- [email protected] To unsubscribe send an email to [email protected] https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/[email protected]/message/L62PAUPNVPZ47SNSMWOW2O3WRTZ3CAHI/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] Re: PEP 622 version 2 (Structural Pattern Matching)
On Fri, 17 Jul 2020, Ethan Furman wrote: The problem with any kind of sigil/keyword is that it becomes line noise -- we would have to train ourselves to ignore them in order to see the structure and variables we are actually interested in. Once we become adept at ignoring them, we will again have difficulties when debugging as we won't easily see them. Besides which, the problem is solved: - namespace.var is a lookup - var is a store Regardless how hard this is being pushed, I beg to disagree. Matching is easy to think of as an extension of destructuring assignment, and could easily be that, if we just don't introduce incompatible rules. Everything currently allowed in an assignment is a store, so it follows that the markup for lookups must be something that is not currently allowed in an assignment. Besides literal constants, my preference is for ``` == x ```, with the obvious opening for future extension. /Paul ___ Python-Dev mailing list -- [email protected] To unsubscribe send an email to [email protected] https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/[email protected]/message/GASEWDEUNW7WNEDRD4JBF2HJ3AU26OJY/ Code of Conduct: http://python.org/psf/codeofconduct/
