[Python-Dev] Re: PEP 622 and variadic positional-only args

2020-07-16 Thread Tobias Kohn

 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

2020-07-16 Thread Tobias Kohn

 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?

2020-07-16 Thread arajgure
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

2020-07-16 Thread Baptiste Carvello
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?

2020-07-16 Thread Eric V. Smith
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

2020-07-16 Thread Eric Nieuwland

> 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

2020-07-16 Thread Federico Salerno
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)

2020-07-16 Thread Steve Holden
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)

2020-07-16 Thread Rhodri James

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)

2020-07-16 Thread MRAB

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)

2020-07-16 Thread Federico Salerno

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)

2020-07-16 Thread Chris Angelico
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)

2020-07-16 Thread Richard Damon
> 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

2020-07-16 Thread Oscar Benjamin
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)

2020-07-16 Thread MRAB

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)

2020-07-16 Thread Glenn Linderman

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

2020-07-16 Thread Tobias Kohn

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