Re: Pattern Matching in Python

2021-02-11 Thread Gavin Bierman
Yes, it’s interesting, and it’s a real improvement to the language. Tobias Kohn 
gave a very nice talk at SPLASH last year that’s worth watching. (It’s purely a 
coincidence that Cambridge seems to be a centre for pattern matching!)

https://www.youtube.com/watch?v=pxQZhL2ZHJU

The treatment of a pattern being an expression with named holes is very nice. 
Unfortunately, it’s really not so simple for us - we’d end up with something 
like : e instanceof new R(x, y). The `new` feels like clutter, doesn’t fit so 
well with subtyping, and we don’t allow local variable declarations like `x`, 
etc etc.

That said, we are aiming for a lot more (although I haven’t followed their 
discussions very closely). Once we get to defining instance patterns etc we 
have gone way beyond simple pattern matching of many languages.

Gavin

On 11 Feb 2021, at 09:34, Remi Forax 
mailto:fo...@univ-mlv.fr>> wrote:

Hi all,
in the news, Python have been accepted the PEP 642, Pattern Matching in Python 
[1].

The accepted PEP is https://www.python.org/dev/peps/pep-0642/
And the rational is https://www.python.org/dev/peps/pep-0635/

Compared to us,
- bindings are visually like variables not a special keyword (a previous 
proposal was using 'as')
 so "case foo:" capture the value inside and store it into foo which is 
obviously very controversial
 (it's even worst because "foo" doesn't have to be a fresh variable).
 I'm happy that we have not chosen that way :)

- guards are introduced with "if", which i find more readable than & or &&.
 Using 'if' can be an issue for us because it means that we can not have a 
guard inside the instanceof pattern, but i am not sure this is really a problem.

- constants can be used directly
 I'm still on the fence about that, it's certainly confusing that case 
Point(0,0) means case Point(var x, var y) if x == 0 && y == 0 and not
 equals(new Point(0,0)) but i understand the arguments that people don't care 
because the result is identical and bloating the syntax to make the semantics 
extra clear
 like in C#, case Point(== 0, == 0) doesn't worth the fuss.

- no support for comma separated values because the syntax is too close to the 
tuple syntax,
 we have already chosen to support comma separated values but only at top 
level, not inside a nested pattern.
 They have introduced '|' for OR and it can be used as top level and inside 
nested patterns.
 Note: in Java, using ',' vs '|' in the syntax is not something new, we are 
using '|' for catch and not ','.
 So question, should we introduce a OR pattern ??

- no support for AND and NOT pattern,
 because as i said in an early mail, using tuples is already an implicit AND.

regards,
Rémi

[1] https://lwn.net/Articles/845480/



Re: Pattern Matching in Python

2021-02-11 Thread Brian Goetz
Overall a good read, and a nice window into the problems they view as 
most worth solving (in their world.)  I think they did a good job in 
integrating this into the Python view of the world.


I'll note that the vision of pattern matching we've taken on is somewhat 
more ambitious -- treating patterns as a part of the object model -- and 
so some of the choices they've made make sense only when viewed through 
that perspective, but would not carry over to ours.



The accepted PEP is https://www.python.org/dev/peps/pep-0642/
And the rational is https://www.python.org/dev/peps/pep-0635/


It's a little hard to follow these.  634/635 seem to be the spec and 
rationale respectively for the basics, and 642 is an alternative syntax 
to 634.  But 634 is listed as Accepted whereas 642 is listed as Draft.  
Are you saying 642 was accepted now?



Compared to us,
- bindings are visually like variables not a special keyword (a previous 
proposal was using 'as')
634 uses "x" and 642 uses "as x".  So that makes 642 the "previous", 
even though it is later numbered?

   so "case foo:" capture the value inside and store it into foo which is 
obviously very controversial
   (it's even worst because "foo" doesn't have to be a fresh variable).
   I'm happy that we have not chosen that way :)


This is a nice example of how what makes sense in one language doesn't 
make sense in another.  Java is statically typed, so declarations of 
pattern variables should look like declarations.


We do have an open question, though, as to whether we want to support a 
way to have a pattern bind to an existing variable.  This shows up when 
writing patterns that want to delegate to other patterns to get some of 
their bindings; if we don't support this, then writing these patterns 
becomes more clunky (have to make up silly extra names.)  Obviously 
something like


    int x;
    if (t instanceof Foo(x)) { ... }

is going to be too cryptic (is it an invocation with x, or a binding of 
x?), but an additional syntactic hint (``, `x=`, `bind x`, etc)  Not 
to be painted here, just registering this as being on the open-questions 
list.



- guards are introduced with "if", which i find more readable than & or &&.
   Using 'if' can be an issue for us because it means that we can not have a 
guard inside the instanceof pattern, but i am not sure this is really a problem.


This is one of those examples that makes sense under "less ambitious 
target."  If your patterns are simpler, you are less likely to combine 
the with each other (witness, they have no & patterns), and therefore 
less likely to need to treat guards unformly.  So nailing guards on the 
side (as almost all languages do) as part of the construct works fine in 
that case.  I think for us, this would bite us as patterns got richer.



- constants can be used directly
   I'm still on the fence about that, it's certainly confusing that case Point(0,0) 
means case Point(var x, var y) if x == 0 && y == 0 and not
Yes, at first look, constant patterns look very cool, but then you 
realize that they don't really buy you that much, and you're bouncing 
out to guards pretty quickly anyway.  So the space in between "patterns 
plus guards" and "patterns plus constant patterns plus guards" is pretty 
small; the return on complexity there seems low.


One place where we might want to revisit this is when we get to 
structural patterns; using  a string literal as a map value is likely to 
be pretty useful.  (We need to do collection literals first, and 
collection literals and patterns are duals just as constructors and 
deconstructors are.)



   like in C#, case Point(== 0, == 0) doesn't worth the fuss.
Agree, at least for now.  We can revisit when we get to "collection 
patterns".



- no support for comma separated values because the syntax is too close to the 
tuple syntax,
   we have already chosen to support comma separated values but only at top 
level, not inside a nested pattern.
   They have introduced '|' for OR and it can be used as top level and inside 
nested patterns.
   Note: in Java, using ',' vs '|' in the syntax is not something new, we are 
using '|' for catch and not ','.
   So question, should we introduce a OR pattern ??
We had an OR pattern (which corresponds to special treatment of bindings 
when merging two expressions with ||, such as `(x instanceof Foo(var a) 
|| x instanceof Bar(var a)`.)  We backed off on this at least 
temporarily because people were concerned about "variables with multiple 
declarations", and this isn't relevant until we have deconstruction 
patterns anyway, so it is "to be revisited."

- no support for AND and NOT pattern,
   because as i said in an early mail, using tuples is already an implicit AND.


Additional thoughts:

 - It's sad that they went the "moar statements" route.
 - They went the "merging" route with OR patterns that we considered, 
but at least temporarily backed off of.  This is a reasonable fit for 
their style of 

Pattern Matching in Python

2021-02-11 Thread Remi Forax
Hi all,
in the news, Python have been accepted the PEP 642, Pattern Matching in Python 
[1].

The accepted PEP is https://www.python.org/dev/peps/pep-0642/
And the rational is https://www.python.org/dev/peps/pep-0635/

Compared to us,
- bindings are visually like variables not a special keyword (a previous 
proposal was using 'as')
  so "case foo:" capture the value inside and store it into foo which is 
obviously very controversial
  (it's even worst because "foo" doesn't have to be a fresh variable).
  I'm happy that we have not chosen that way :)  

- guards are introduced with "if", which i find more readable than & or &&.
  Using 'if' can be an issue for us because it means that we can not have a 
guard inside the instanceof pattern, but i am not sure this is really a problem.

- constants can be used directly
  I'm still on the fence about that, it's certainly confusing that case 
Point(0,0) means case Point(var x, var y) if x == 0 && y == 0 and not
  equals(new Point(0,0)) but i understand the arguments that people don't care 
because the result is identical and bloating the syntax to make the semantics 
extra clear
  like in C#, case Point(== 0, == 0) doesn't worth the fuss.

- no support for comma separated values because the syntax is too close to the 
tuple syntax,
  we have already chosen to support comma separated values but only at top 
level, not inside a nested pattern.
  They have introduced '|' for OR and it can be used as top level and inside 
nested patterns.
  Note: in Java, using ',' vs '|' in the syntax is not something new, we are 
using '|' for catch and not ','.
  So question, should we introduce a OR pattern ??

- no support for AND and NOT pattern,
  because as i said in an early mail, using tuples is already an implicit AND.

regards,
Rémi

[1] https://lwn.net/Articles/845480/