[Python-Dev] Re: PEP 622 and variadic positional-only args
Hi Oscar On Wed, Jul 15, 2020 at 4:41 PM Oscar Benjamin wrote: I've taken a look through PEP 622 and I've been thinking about how it could be used with sympy. Thank you very much for taking the time to carefully elaborate an interesting possible use case. I find this very helpful and a great basis for further/future discussions on the design of pattern matching. A deliberate part of the current design was to address the /structure/shape/ of objects rather than the constructor directly (which could be an arbitrary complex function after all). Writing `Add(args=(Mul(...), Mul(...))` for instance is therefore consistent as it reflects the /actual structure/ of your objects. The `__match_args__` is primarily intended for rather simple object shapes, where it is quite obvious what attributes constitute the object and in which order (similar to the `_fields` attribute in AST nodes). From this perspective, your use case makes an argument for something I would call '/variadic shape/' (in lack of a better word). Structurally, your objects behave like sequences or tuples, adorned with a specific type/class---which, again, is currently expressed as the "class(tuple)" pattern such as `Add((Mul(), Mul()))`. There are two possibilities to approach this issue. We could introduce patterns that extract "sequential elements" via `__getitem__` rather than attributes. Or we could have a special method `__match__` that might return a representation of the object's data in sequential form. The `__getitem__` approach turned out to come with quite a few complications. In short: it is very hard to assess an object's possibly sequential structure in a non-destructive way. Because of the multiple cases in the new pattern matching structure, we cannot just use an iterator as in unpacking. And `__getitem__` itself is extremely versatile, being used, e.g., for both sequences as well as mappings. We therefore ended up supporting only built-in structures like tuples, list, and dicts for now, for which the interpreter can easily determine how to handle `__getitem__`. The `__match__` protocol, on the other hand, is something that we deferred so that we can make sure it really is powerful and well designed enough to handle a wide range of use cases. One of the more interesting use cases, e.g., I had in mind was to destructure data that comes as byte strings, say (something that Rhodri James [1] has brought up, too). And I think you have just added another very interesting use case to take into consideration. But probably the best course of action is really to gain some experience and collect some additional use cases. Kind regards, Tobias [1] https://mail.python.org/archives/list/[email protected]/message/WD2E3K5TWR4E6PZBM4TKGHTJ7VDERTDG/ ___ 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/PDZZGP6TY5G2SJBY2SII4W5GCO3B64PQ/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] Re: PEP 622 constant value syntax idea
Hi Mohammad, In addition to what Rhodri James has already well pointed out, here are two additional thoughts on this. At the moment, the keyword `global` is a marker to say that the respective variable is /modified/ by a function. Your suggestion would invert that meaning and might therefore add more confusion than what it would solve. Moreover, to provide yet another alternative, you could also define something along the lines of: this = sys.modules[__name__] and then write: MATCH value: CASE this.x: ... Of course, this is a bit of a hack and not that much different to using SimpleNamespace. But it demonstrates that any such keyword would not really add that much power or save any keystrokes. In the end, I can well imagine that a future version of Python might add something like a "read and compare" marker to patten matching. But it is probably a good idea to start with a set of fully working but rather minimalistic core features, and then let it grow and evolve with time, guided by real use cases and issues that we run into. Kind regards, Tobias ___ 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/MJGSHTSPUXYCWEYCF5S6QGIMNAFP6ZSY/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] Problems with python and Geany?
So I have recently purchased a rapsberry pi in hope that it will ease me in to programming and learn a bit more about computing. I was reading an article in pc pro about creating a game using python so thought I would give it a shot. However, when I try to execute on Geany I keep getting the same message : "09:13:05: Failed to execute "C:\Python27\python "raspberry.py"" (start-script could not be created: Failed to create file: Permission denied)" I've been searching google and forums for answers as I cannot see why this is not working Any ideas? Anyone?! https://www.sevenmentor.com/best-python-classes-in-pune.php ___ 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/JGADR2R4ULSORZ6XU25KNC5ARBVT2IMK/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] Re: PEP 622 constant value syntax idea
Hello,
Le 15/07/2020 à 13:37, Mohammad Foroughi via Python-Dev a écrit :
> Hi, I had an idea regarding the pattern matching issue of comparing with
> a previous constant variable instead of assigning to a new local
> variable. I'm not sure if this has been brought up before but instead of
> using a symbol with the case statement what if we used a keyword.
>
> [...]
>
> Other ideas for the keyword are "const" or "static" but these 2 are more
> difficult to recognise since they aren't in other parts of python but
> the "global" keyword is already implemented so it would be easy to
> understand.
What about simply "is", which is already a keyword?
AFAIK "is" has no meaning as a prefix operator as of now, so hopefully
it would not make the grammar ambiguous (how can one check that for sure?).
match color:
case is RED:
print("red")
case is BLUE:
print("blue")
case other:
print(f"unknown color {other}")
or with Rhodri James' example:
match value:
case is x:
print("value matches")
case Point(is x, y):
print("value matches x, y captured")
case Line(Point(is x1, y1), Point(x2, is y2)):
print("wouldn't call that pretty, but not ugly either")
Cheers,
Baptiste
P.S.: granted, it could mislead some users into thinking that the
comparison is done with "is" instead of "=="; but then, patterns are
special in many ways, users will have to just learn them…
___
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/TZEJHFALXL4OUBDYNQ5D6PEALUYHG57I/
Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] Re: Problems with python and Geany?
This list is for the development of Python the language. For end-user help, you're better off using python-list, whose details are here: https://mail.python.org/mailman/listinfo/python-list Eric On 7/16/2020 8:00 AM, [email protected] wrote: So I have recently purchased a rapsberry pi in hope that it will ease me in to programming and learn a bit more about computing. I was reading an article in pc pro about creating a game using python so thought I would give it a shot. However, when I try to execute on Geany I keep getting the same message : "09:13:05: Failed to execute "C:\Python27\python "raspberry.py"" (start-script could not be created: Failed to create file: Permission denied)" I've been searching google and forums for answers as I cannot see why this is not working Any ideas? Anyone?! https://www.sevenmentor.com/best-python-classes-in-pune.php ___ 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/JGADR2R4ULSORZ6XU25KNC5ARBVT2IMK/ 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/5W6R3MSOT7IWAIBTB7Z35AUMB4N5IVKJ/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] Re: PEP 622 constant value syntax idea
> From: Baptiste Carvello
> Subject: [Python-Dev] Re: PEP 622 constant value syntax idea
>
> What about simply "is", which is already a keyword?
>
> AFAIK "is" has no meaning as a prefix operator as of now, so hopefully
> it would not make the grammar ambiguous (how can one check that for sure?).
>
> match color:
>case is RED:
>print("red")
>case is BLUE:
>print("blue")
>case other:
>print(f"unknown color {other}")
>
> or with Rhodri James' example:
>
> match value:
>case is x:
>print("value matches")
>case Point(is x, y):
>print("value matches x, y captured")
>case Line(Point(is x1, y1), Point(x2, is y2)):
>print("wouldn't call that pretty, but not ugly either")
>
>
> Cheers,
> Baptiste
>
> P.S.: granted, it could mislead some users into thinking that the
> comparison is done with "is" instead of "=="; but then, patterns are
> special in many ways, users will have to just learn them…
That is exactly why I think you should make the special things special and keep
the familiar things as you know them.
So constants and variables like they are in other uses and matched
values/patterns using a special construction/syntax.
And we don’t need the catch all case if we would have the IMHO more familiar:
match Color(…) as color:
case RED:
print(f”{color} is red")
case BLUE:
print(f”{color} is blue”)
else:
print(f"unknown color {color}”)
thus eliminating the whole ‘case ’ issue.
___
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/4NTH5H6RX2KTVVJFJUF53UWESJIBCLYS/
Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] PEP 622 idea: "match case object" to represent match patterns
Recent discussion on the store vs. load syntax issues of PEP 622
prompted a (yet unripe) idea that could hopefully spur some progress.
What if cases required some sort of MatchCase (name pending) object
which could be preconstructed by the user if needed, but also inferred
on the fly if absent? I think an example would clarify what I mean.
Consider the following block (with & to mark "load" just for
demonstration purposes):
match some_point:
case Point(x, y, _) if x > y:
print(f"Tridimensional point with x > y")
case Point(_, _, _):
print("Some other 3D point.")
case Point(_, &my_y) as pt:
print(f"{pt} has y=={my_y}.")
case Point(10, _):
print("Some bidimensional point with x==10.")
case Point(_, y):
print(f"Bidimensional point with {y=}.")
case _:
print("Something else.")
This is admittedly simple enough that it wouldn't require what I'm about
to show, but it does require marking my_y in some way to prevent it from
being interpreted as a "store" identifier, or to namespace it for the
same reason. 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 _:
...
Every case above could be constructed in the same way as in the example
without MatchCase, except for point_with_my_y, which contains a lookup:
every identifier inside the match is interpreted as "store" unless it's
namespaced; the others are included for demonstration purposes.
As seen in case Point(10, _), patterns that contain no "load"
identifiers can be written without using MatchCase instances. In effect,
its usage would be a sort of "plug-in" for when complex or verbose
functionality is needed, allowing to load identifiers or encode patterns
for readability and/or reuse through the match block.
The value of the identifiers to load would be read at MatchCase
instantiation and internally converted to a constant value.
Guard clauses could optionally be included in the MatchCase
instantiation. If both it and the case: provide guards, they are anded
together.
If deemed appropriate, a special meaning could be given to MatchCase()
(no arguments, or with "" or even any falsy value as argument) to
represent the default case to appease those who don't like _.
Note that the above examples assume at least _ (and possibly any
identifier) can be repeated. My proposed MatchCase idea is compatible
with the possibility of disallowing repeated identifiers, while still
allowing them in MatchCase()'s first argument with the behaviour seen in
the other_3d_point case.
The constructor MatchCase could be either provided as a builtin or in a
stdlib module that must be imported. I think the latter would be more
reasonable.
Any specific syntax or name presented above (MatchCase, the {}s in its
first argument, the names of the MatchCase.args and MatchCase.kwargs
attributes) is debatable.
I hope I haven't missed any important point that would make the above
demonstration invalid. Any thoughts?
___
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/DDYISJOZPJOD2C2RY4HH2XS3YMHBVYWX/
Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] Re: PEP 622 version 2 (Structural Pattern Matching)
While I understand the point of view that says that match ... : should encapsulate a sequence of indented suites, it seems to me that match/case/case/.../else has a natural affinity with try/except/except/.../finally/else, and nobody seems to think that the excepts should be indented. Or the finally. And naturally the match/else case are at the same indentation level, just as for/else, while/else and try/finally. So why, exactly, should case be indented? My apologies for being a Bear of Very Little Brain. On Fri, Jul 10, 2020 at 12:09 PM Greg Ewing wrote: > A thought about the indentation level of a speculated "else" clause... > > Some people have argued that "else" should be at the outer level, > because that's the way it is in all the existing compound statements. > > However, in those statements, all the actual code belonging to the > statement is indented to the same level: > > if a: > > elif b: > > else: > > > ^ > | > Code all indented to this level > > But if we were to indent "else" to the same level as "match", > the code under it would be at a different level from the rest. > > match a: > case 1: > > case 2: > > else: > > ^ ^ > | | > Code indented to two different levels > > This doesn't seem right to me, because all of the cases, including > the else, are on the same footing semantically, just as they are in > an "if" statement. > > -- > 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/ACH4QXCURTNEGKFQXEWET5NQ6DIABSQZ/ > 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/QAN7C4LJFLJ5U6SWZRH6ANRMHYEWHMBG/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] Re: PEP 622 version 2 (Structural Pattern Matching)
On 16/07/2020 17:37, Steve Holden wrote: While I understand the point of view that says that match ... : should encapsulate a sequence of indented suites, it seems to me that match/case/case/.../else has a natural affinity with try/except/except/.../finally/else, and nobody seems to think that the excepts should be indented. Or the finally. And naturally the match/else case are at the same indentation level, just as for/else, while/else and try/finally. So why, exactly, should case be indented? My take on the difference would be that "try" tries out a suite, while "match" matches an expression. If we did: match: case : then having an indented section which must be a single expression would be unique in Python syntax. I could easily see people being confused when the slew of statements they would inevitably decide they must be able to put there, and soon we'd have cats and dogs living together and the downfall of civilisation as we know it. Alternatively: match : case : would be the one place in Python where you end a line with a colon and *don't* indent the following line. Writers of simple formatters and the like (such as Python-mode in Emacs) would curse your name, etc, etc. My apologies for being a Bear of Very Little Brain. Nah, don't apologise. This is one of those things that everyone has opinions on, because there doesn't seem to be an obvious Right Answer. -- Rhodri James *-* Kynesim Ltd ___ 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/JYDDPBDO56EQWTFSWY2NNDNT2NDHWXG5/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] Re: PEP 622 version 2 (Structural Pattern Matching)
On 2020-07-16 17:37, Steve Holden wrote: While I understand the point of view that says that match ... : should encapsulate a sequence of indented suites, it seems to me that match/case/case/.../else has a natural affinity with try/except/except/.../finally/else, and nobody seems to think that the excepts should be indented. Or the finally. And naturally the match/else case are at the same indentation level, just as for/else, while/else and try/finally. So why, exactly, should case be indented? My apologies for being a Bear of Very Little Brain. [snip] For all other statement structures (if, while, try, etc.), the first line ends with a colon and the second line is indented (and is a statement). Therefore the cases should be indented. However, for all other statement structures (if, while, try, etc.), the other parts of the structure itself (elif, else, except, etc.) aren't indented. Therefore the cases shouldn't be indented. Either way, it's inelegant. ___ 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/4W2J5SLLOTLPMMFIZ4KTAC4THJMDCWBW/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] Re: PEP 622 version 2 (Structural Pattern Matching)
On 16/07/2020 19:00, Rhodri James wrote: On 16/07/2020 17:37, Steve Holden wrote: While I understand the point of view that says that match ... : should encapsulate a sequence of indented suites, it seems to me that match/case/case/.../else has a natural affinity with try/except/except/.../finally/else, and nobody seems to think that the excepts should be indented. Or the finally. And naturally the match/else case are at the same indentation level, just as for/else, while/else and try/finally. So why, exactly, should case be indented? [...] If we did: match: case : then having an indented section which must be a single expression would be unique in Python syntax. [...] match : case : would be the one place in Python where you end a line with a colon and **don't** indent the following line. It seems relevant to mention that before Python's unique syntax for a ternary operator (x = something if something else default_value), you would never find an if or else without a colon and an indented block, and the order (value, condition, default) is different than what is usually found in other languages (condition, value, default). That hasn't stopped Python from implementing the feature in its own way and I don't see why this PEP should be different, since Python is not other languages and match suites are not other suites. I could easily see people being confused when the slew of statements they would inevitably decide they must be able to put there, and soon we'd have cats and dogs living together and the downfall of civilisation as we know it. [...] Writers of simple formatters and the like (such as Python-mode in Emacs) would curse your name, etc, etc. Tools should adapt to the language, not the other way around. If things had to be done the way they had always been done, without any change, for fear of people not being used to it, we wouldn't even have Python at all. People learn and adapt. It seems like a small price to pay in exchange for consistency and removal of ambiguity, considering people will still have to learn the new feature one way or another. ___ 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/6KUIVENOCYIZSGXCLX6O5V3OJDIXO235/ 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:25 AM Federico Salerno wrote: > Tools should adapt to the language, not the other way around. If things had > to be done the way they had always been done, without any change, for fear of > people not being used to it, we wouldn't even have Python at all. People > learn and adapt. It seems like a small price to pay in exchange for > consistency and removal of ambiguity, considering people will still have to > learn the new feature one way or another. > But consistency is exactly what you'd be destroying here. Python is extremely consistent in that you ALWAYS indent after a line ends with a colon, and what comes after it is logically contained within that statement. It's about whether *people* can handle it, more than whether tools can, and the consistency helps a lot with that. ChrisA ___ 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/S56BYBQIWTV2SQYBTYT3ZRPNI7CLF5MR/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] Re: PEP 622 version 2 (Structural Pattern Matching)
> On Jul 16, 2020, at 1:36 PM, Chris Angelico wrote: > > On Fri, Jul 17, 2020 at 3:25 AM Federico Salerno > wrote: >> Tools should adapt to the language, not the other way around. If things had >> to be done the way they had always been done, without any change, for fear >> of people not being used to it, we wouldn't even have Python at all. People >> learn and adapt. It seems like a small price to pay in exchange for >> consistency and removal of ambiguity, considering people will still have to >> learn the new feature one way or another. >> > > But consistency is exactly what you'd be destroying here. Python is > extremely consistent in that you ALWAYS indent after a line ends with > a colon, and what comes after it is logically contained within that > statement. It's about whether *people* can handle it, more than > whether tools can, and the consistency helps a lot with that. > > ChrisA > One question that comes to mind, does match NEED a colon at the end of it? If it didn’t have the colon, it wouldn’t need the indent for the following lines. ___ 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/M7CVHHBR5IGIUCFH4Y7S6I7FQWXTEE64/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] Re: PEP 622 and variadic positional-only args
On Thu, 16 Jul 2020 at 02:09, Guido van Rossum wrote:
>
> On Wed, Jul 15, 2020 at 4:41 PM Oscar Benjamin
> wrote:
>>
>> I've taken a look through PEP 622 and I've been thinking about how it
>> could be used with sympy.
>>
>> In principle case/match and destructuring should be useful for sympy
>> because sympy has a class Basic which defines a common structure for
>> ~1000 subclasses. There are a lot of places where it is necessary to
>> dispatch on the type of some object including in places that are
>> performance sensitive so those would seem like good candidates for
>> case/match. However the PEP doesn't quite seem as I hoped because it
>> only handles positional arguments indirectly and it does not seem to
>> directly handle types with variadic positional args.
>>
[snip]
>>
>> From a first glimpse of the proposal I thought I could do matches like this:
>>
>> match obj:
>> case Add(Mul(x, y), Mul(z, t)) if y == t:
>> case Add(*terms):
>> case Mul(coeff, *factors):
>> case And(Or(A, B), Or(C, D)) if B == D:
>> case Union(Interval(x1, y1), Interval(x2, y2)) if y1 == x2:
>> case Union(Interval(x, y), FiniteSet(*p)) | Union(FiniteSet(*p),
>> Interval(x, y)):
>> case Union(*sets):
>>
>> Knowing the sympy codebase each of those patterns would look quite
>> natural because they resemble the constructors for the corresponding
>> objects (as intended in the PEP). It seems instead that many of these
>> constructors would need to have args= so it becomes:
>>
>> match obj:
>> case Add(args=(Mul(args=(x, y)), Mul(args=(z, t if y == t:
>> case Add(args=terms):
>> case Mul(args=(coeff, *factors)):
>> case And(args=(Or(args=(A, B)), Or(args=(C, D if C == D:
>> case Union(args=(Interval(x1, y1), Interval(x2, y2))) if y1 == x2:
>> case Union(args=(Interval(x, y), FiniteSet(args=p))) |
>> Union(args=(FiniteSet(args=p), Interval(x, y))):
>> case Union(args=sets):
>>
>> Each of these looks less natural as they don't match the constructors
>> and the syntax gets messier with nesting.
>
>
> That's a really interesting new use case you're bringing up.
>
> You may have noticed that between v1 and v2 of the PEP we withdrew the
> `__match__` protocol; we've been brainstorming about different forms a future
> `__match__` protocol could take, once we have more practical experience. One
> possible variant we've been looking at would be something that would *only*
> be used for positional arguments -- `__match__` would just return a tuple of
> values extracted from the object that can then be matched by the
> interpreter's match machinery. Your use case could then (almost, see below)
> be handled by having `__match__` just return `self.args`.
That would work but something else just occurred to me which is that
as I understand it the intention of __match_args__ is that it is
supposed to correspond to the parameter list for __init__/__new__ like
class Thing2:
__match_args__ = ('first', 'second')
def __init__(self, first, second):
self.first = first
self.second = second
That is deliberate so that matching can have a similar logic to the
way that arguments are handled when calling __init__:
match obj:
case Thing2(1, 2):
case Thing2(1, second=2):
case Thing2(first=1, second=2):
...
Maybe __match_args__ could have a way to specify the variadic part of
a parameter list as well:
class ThingN:
__match_args__ = ('first', 'second', '*rest')
def __init__(self, first, second, *rest):
self.first = first
self.second = second
self.rest = rest
Then you can match with
match obj:
case ThingN(1, 2):
case ThingN(1, 2, 3):
case ThingN(first, second, *rest):
case ThingN(first, *second_and_rest):
case ThingN(*allargs):
...
The normal restrictions for combinations of keyword and positional
arguments could apply to the patterns as if __match_args__ was the
parameter list for a function.
Perhaps the * in '*rest' isn't as clear between quotes and some more
noticeable syntax could be used like
__match_args__ = ('first', 'second', ('rest',))
--
Oscar
___
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/SMN5GZHGURK2AQKTBES5Z6XLWPDUBNB6/
Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] Re: PEP 622 version 2 (Structural Pattern Matching)
On 2020-07-16 19:05, Richard Damon wrote: On Jul 16, 2020, at 1:36 PM, Chris Angelico wrote: On Fri, Jul 17, 2020 at 3:25 AM Federico Salerno wrote: Tools should adapt to the language, not the other way around. If things had to be done the way they had always been done, without any change, for fear of people not being used to it, we wouldn't even have Python at all. People learn and adapt. It seems like a small price to pay in exchange for consistency and removal of ambiguity, considering people will still have to learn the new feature one way or another. But consistency is exactly what you'd be destroying here. Python is extremely consistent in that you ALWAYS indent after a line ends with a colon, and what comes after it is logically contained within that statement. It's about whether *people* can handle it, more than whether tools can, and the consistency helps a lot with that. ChrisA One question that comes to mind, does match NEED a colon at the end of it? If it didn’t have the colon, it wouldn’t need the indent for the following lines. All of the others have the colon. ___ 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/Z63GPE46RPULXJRIFVOBF4DDM3BCKD5B/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] Re: PEP 622 version 2 (Structural Pattern Matching)
On 7/16/2020 10:00 AM, Rhodri James wrote: On 16/07/2020 17:37, Steve Holden wrote: While I understand the point of view that says that match ... : should encapsulate a sequence of indented suites, it seems to me that match/case/case/.../else has a natural affinity with try/except/except/.../finally/else, and nobody seems to think that the excepts should be indented. Or the finally. And naturally the match/else case are at the same indentation level, just as for/else, while/else and try/finally. So why, exactly, should case be indented? My take on the difference would be that "try" tries out a suite, while "match" matches an expression. If we did: match: case : then having an indented section which must be a single expression would be unique in Python syntax. I could easily see people being confused when the slew of statements they would inevitably decide they must be able to put there, and soon we'd have cats and dogs living together and the downfall of civilisation as we know it. Alternatively: match : case : would be the one place in Python where you end a line with a colon and *don't* indent the following line. Writers of simple formatters and the like (such as Python-mode in Emacs) would curse your name, etc, etc. My apologies for being a Bear of Very Little Brain. Nah, don't apologise. This is one of those things that everyone has opinions on, because there doesn't seem to be an obvious Right Answer. Speaking of things unique in Python syntax, isn't double-indention of a single control flow structure introduced by match also unique? ___ 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/E26GHBGQCGROPUJZBRY66GVKDWOQT4ZX/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] Another take on PEP 622
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. Let's start with perhaps the most crucial part: PEP 622 does **NOT** propose to introduce a `switch`-statement! Indeed, pattern matching is much more closely related to concepts like regular expressions, sequence unpacking, visitor patterns, or function overloading. In particular, the patterns themselves share more similarities with formal parameters than with expressions. So, to start with I would like to invite you to think of PEP 622 not so much as proposing a new control structure in the sense of `if`-`elif`-`else`, `try`-`except`-`finally`, or even `switch`, but much rather as addressing the question: what would function overloading look like in Python? Of course, this does not fully capture pattern matching or do it justice, either, but it might offer a better basis to start with. 1. Function Overloading --- In a statically typed language, you might define a function `product` that either accepts two numbers or an iterable something like the following (I am sticking to Python syntax for simplicity): ``` def product(a: float, b: float) -> float: return a * b def product(it: Iterable[float]) -> float: result = 1.0 for x in it: result *= x return result ``` In Python, however, this needs to be done differently and the dispatch logic has to be put inside the function itself: ``` def product(*args): if len(args) == 2 and isinstance(args[0], float) and isinstance(args[1], float): return args[0] * args[1] elif len(args) == 1 and isinstance(args[0], Iterable): result = 1.0 for x in args[0]: result *= x return result ``` It is this use case to begin with that pattern matching is addressing by introducing a more declarative way. Each `case` represents one possibility of what the parameter list might look like: ``` def product(*args): match args: case (float(a), float(b)): return a * b case (Iterable(it),): result = 1.0 for x in it: result *= x return result ``` And if you squint a little, you might even see that these parameter lists could almost be written in C: `(float a, float b)`. In the context of more functional languages, you might also have seen some wilder stuff, where function overloading allows you to include literals. One of the most prevalent examples is the factorial function, usually defined a bit like this: ``` def fact(0): return 1 def fact(n): return n * fact(n-1) ``` Again, when doing the same thing in Python, we put the dispatch logic inside the function: ``` def fact(n): if n == 0: return 1 else: return n * fact(n - 1) ``` It is only natural to also allow pattern matching to express this use case: ``` def fact(arg): match arg: case 0: return 1 case n: return n * fact(n - 1) ``` And this here is where you probably start to see good old `switch` coming in. Indeed, pattern matching is powerful and versatile enough to act as a `switch` replacement in many cases. But given how we arrived here, you might start to understand that this is a happy accident and not by design of the structure itself. There is one big elephant in the room, of course: why do we need the `match`-line in the first place? If all we want is to somehow express function overloading, couldn't we just put the cases directly into the function body? In principle, yes, we could do that. But! As it turns out, there is something to be gained by a clear separation. When actually using pattern matching, you might discover that you do not always want to define a function. Sometimes, it is quite convenient being able to have a pattern like this, for instance: ``` def foo(*args): for arg in args: match arg: case ... ``` In all of these examples, it looks as if pattern matching is replacing an `if`-`elif`-`else` chain. However, this is not entirely accurate. What we really want to express is the function overloading in the first place. The `if`s are only needed to express the same idea in Python for the time being. In other words: the individual cases here express independent implementations and we leave it up to the Python interpreter to choose the right one. 2. Visitor Pattern and Dispatch --- If you wanted to implement something like function overloading based on the type of the argument, you might use the _visitor pattern_ for that purpose. Thanks to Py
