[Python-Dev] Re: PEP 622 version 2 (Structural Pattern Matching)

2020-08-04 Thread Tobias Kohn

 Hi Larry,

You are right that just dismissing intuition is wrong.  I should have  
been more careful with my wording or explain them better, and I would  
like to apologise if my response came across as too strong in this  
regard.


The actual problem that I see is that we have different  
cultures/intuitions fundamentally clashing here.  In particular, so  
many programmers welcome pattern matching as an "extended switch  
statement" and find it therefore strange that names are binding and  
not expressions for comparison.  Others argue that it is at odds with  
current assignment statements, say, and question why dotted names are  
_/not/_ binding.  What all groups seem to have in common, though, is  
that they refer to _/their/_ understanding and interpretation of the  
new match statement as 'consistent' or 'intuitive'---naturally  
pointing out where we as PEP authors went wrong with our design.


But here is the catch: at least in the Python world, pattern matching  
as proposed by this PEP is an unprecedented and new way of approaching  
a common problem.  It is not simply an extension of something already  
there.  Even worse: while designing the PEP we found that no matter  
from which angle you approach it, you will run into issues of seeming  
'inconsistencies' (which is to say that pattern matching cannot be  
reduced to a 'linear' extension of existing features in a meaningful  
way): there is always something that goes fundamentally beyond what is  
already there in Python.  That's why I argue that arguments based on  
what is 'intuitive' or 'consistent' just do not make sense _/in this  
case/_.  I think the discussion on this mailing list with the often  
contradictory views, proposals, and counter-proposals more than makes  
my point.


As for your argument that it looks like calling a function or creating  
an object: I tried to explain a little while ago that you'd be well  
advised to rather approach it as something similar to a function  
_/definition/_.  After all, the part after `def` in `def foo(a, b):`  
also looks like a function call!  But nobody seems to mind this  
similarity in syntax there!  And the target in `(a, b) = c` looks like  
a tuple constructor, although it actually is the exact opposite.


Finally, I completely agree that intuition is informed by experience  
and serving us very well.  The first part of this, however, is also to  
say that intuition is malleable thing!  And experience from other  
programming languages who took the leap to having pattern matching  
shows that it quickly becomes a quite intuitive and easy to use feature.


Cheers,
Tobias

P.S. Please excuse my late reply; I am currently on vacation.

Quoting Larry Hastings :


 
  On 7/31/20 12:36 AM, Tobias Kohn wrote:


And since pattern matching is really
a new feature to be introduced to Python, a feature that can
be seen in different lights, there is no 'Python-Programmer
intuition' that would apply in this case.


  It's not fair to say "intuition doesn't apply because it's new  
syntax".  There are plenty of examples of intuition serving a Python  
programmer well when encountering new syntax.  A Python programmer's  
intuition is informed by existing syntax and conventions in the  
language.  When they see a new construct, its similarity to existing  
constructs can make understanding the new syntax quite intuitive  
indeed.


  Take for example list comprehensions.  Python 1 programmers hadn't seen


a = [x for x in y]


  But they knew what square brackets meant in that context, it meant  
"creates a new list".  And they knew what "for x in y" meant, that  
meant iteration.  Understanding those separate two concepts, a  
Python 1 programmer would be well on their way to guessing what the  
new syntax meant--and they'd likely be right.  And once they  
understood list comprehensions, the first time they saw generator  
expressions and set and dict comprehensions they'd surely intuit  
what those did immediately.


  The non-intuitiveness of PEP 622, as I see it, is that it  
repurposes what looks like existing Python syntax but frequently has  
wholly different semantics.  For example, a "class pattern" looks  
like it's calling a function--perhaps instantiating an object?--but  
the actual semantics and behavior is very different.  Similarly, a  
"mapping pattern" looks like it's instantiating a dict, but it does  
something very different, and has unfamiliar and seemingly arbitrary  
rules about what is permitted, e.g. you can't use full expressions  
or undotted-identifiers when defining a key.  Add the "capture  
pattern" to both of these, and a Python programmer's intuition about  
what this syntax traditionally does will be of little help when  
encountering a PEP 622 match statement for the first time.


  Cheers,

   

  //arry/
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to 

[Python-Dev] Pattern matching (alternative to PEP 622)

2020-08-04 Thread Koos Zevenhoven
Hi everyone,

By what I'm about to write below, I've aimed at a design to meet needs
resembling those that PEP 622 deals with, although with some differences,
especially in emphasis.

I'm not writing a full introduction here; the intended audience of this
email is people somewhat familiar with PEP 622 and its discussions. This
email doesn't have much structure or anything, but I hope it's sufficiently
clear.

Things that this design aims to address:

* Check whether an object's structure matches a given pattern
* Optionally extract desired values from within that structure
* Learning: patterns are understandable in a logical and consistent manner
* Matching can be easily tinkered with interactively
* Names used in patterns behave in a clear and intuitive way for Python
programmers
* ...

The most difficult thing is perhaps to understand what names mean: what is
being bound to, and what is a value defined elsewhere and so on. For
example, if a (somewhat unrealistic) pattern looks like

Point3D(x=3.14, y=6, z=_)

, there are four names that refer to something: `Point3D`, `x`, `y` and
`z`. To understand this, it is useful to think of the pattern as
corresponding to an expression, although it is not treated as quite the
same in the end. (So, here x, y, z refer to internals/arguments of Point3D)

The situation becomes more difficult when the values to compare with are in
variables, and/or if one wishes to extract a value from the structure.

Point3D(x=pi, y=SIX, z=value)

Now there is no way to tell, from this, which names refer to existing
objects and which should be bound to by the operation, except by guessing.
Here, `value` is supposed to be a binding target.

Python already has destructuring assignment (`a, b, *rest = values`), which
is similar to what happens in function calls: `def func(a, b, *rest): ...`.

However, compared to this, it is more useful to see patterns as working
backwards compared to this. For example, the semantics of the names in

lambda value: Point3D(x=pi, y=SIX, z=value)

are exactly as desired. That is, when the pattern matching is interpreted
as "does this object look like what this function would produce, and if so,
what would be the arguments of the function in that case?". Matching the
pattern would bind to `value`.

So, with this, a previous understanding of function definitions already
gives you a mental model for how names work in patterns *and* for what the
pattern is supposed to do.

In theory, the lambda expression could BE the syntax for a pattern.
However, many have wished for a different syntax even for lambdas. A
slightly nicer form would be to omit the keyword `lambda`, but then one
would still have to repeat the names to be bound. To avoid that, we need a
way to explicitly mark "not-yet-bound names":

Point3D(x=pi, y=SIX, z=value?)

Before going any further, how would one invoke the matching machinery? It
could be

 matches 

and that would evaluate to a boolean-like value.

With this syntax, the `is_tuple` example from PEP 622 would look something
like this:

def is_tuple(node: Node) -> bool:
if node matches Node(children=[LParen(), RParen()]):
return True
elif node matches Node(children=[Leaf(value="("), Node(),
Leaf(value=")")]):
return True
return False

Or something like:

def is_tuple(node: Node) -> bool:
if node matches tuple_pattern:
return True
return False

Here, `tuple_pattern` would be a pattern pre-defined with a function-like
syntax. Also, if there is a `tuple_pattern`, then `is_tuple` is probably
not needed at all.

Note that in PEP 622, is_tuple uses a match statement with three cases. So,
in effect, the full tuple_pattern had been split into subpatterns. This was
only possible because it was an OR pattern. In general, splitting a longer
pattern into cases like that is not possible. Longer function-like
patterns, on the other hand, can be expressed using more pattern functions
– just like regular functions can use helper functions.

Here, tuple_pattern isn't passed any arguments. It also doesn't have any
parameters. However, if it did, those would be considered wildcards, as I
believe we'd want both the programmer and the compiler/optimizers to
explicitly see, from the match expression, which names will/would be bound.
If something other than wildcard behavior is desired, that should be
explicitly specified in a "pattern function call".

Let's take another example pattern:

pdef main_diagonal_point(pos):
return Point3D(pos, pos, pos)

Now, `main_diagonal_point(0)` would refer to the origin, and `point matches
main_diagonal_point` would be true for every point with `x == y == z`.
Similarly, also `point matches main_diagonal_point(pos?)` should only match
if  `x == y == z` — and then bind that value to `pos`. However, one might
expect to be able to write the same thing inline as

point matches Point3D(pos?, pos?, pos?)

, so based on that, multiple occurrences of the same binding target should
ensure 

[Python-Dev] Re: PEP 622 version 2 (Structural Pattern Matching)

2020-08-04 Thread Stefano Borini
On Thu, 16 Jul 2020 at 19:09, Richard Damon  wrote:
> 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.


Or something like

match t case ("rect", real, imag):
return complex(real, imag)
case ("polar", r, phi):
return complex(r * cos(phi), r * sin(phi))
else:
pass



-- 
Kind regards,

Stefano Borini
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/G6HNAS4TMH6DY6QTAYXUZJK5GIRI3MC5/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 624: Remove Py_UNICODE encoder APIs

2020-08-04 Thread Inada Naoki
On Tue, Aug 4, 2020 at 3:31 PM M.-A. Lemburg  wrote:
>
> Hi Inada-san,
>
> thanks for attending EuroPython. I won't be back online until
> next Wednesday. Would it be possible to wait until then to continue
> the discussion ?
>

Of course. The PEP is for Python 3.11. We have a lot of time.

Bests,
-- 
Inada Naoki  
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/YSRQWCOGXHFL6BOYBAFGW72YOTRII5AR/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 624: Remove Py_UNICODE encoder APIs

2020-08-04 Thread M.-A. Lemburg
Hi Inada-san,

thanks for attending EuroPython. I won't be back online until
next Wednesday. Would it be possible to wait until then to continue
the discussion ?

Thanks,
-- 
Marc-Andre Lemburg
eGenix.com

Professional Python Services directly from the Experts
>>> Python Projects, Coaching and Consulting ...  http://www.egenix.com/
>>> Python Database Interfaces ...   http://products.egenix.com/
>>> Plone/Zope Database Interfaces ...   http://zope.egenix.com/


::: We implement business ideas - efficiently in both time and costs :::

   eGenix.com Software, Skills and Services GmbH  Pastor-Loeh-Str.48
D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg
   Registered at Amtsgericht Duesseldorf: HRB 46611
   http://www.egenix.com/company/contact/
  http://www.malemburg.com/


On 04.08.2020 05:13, Inada Naoki wrote:
> Hi, Lemburg.
> 
> Thank you for organizing the EuroPython 2020.
> I enjoyed watching some sessions from home.
> 
> I think current PEP 624 covers all your points and ready for Steering
> Council discussion.
> Would you like to review the PEP before it?
> 
> Regards,
> 
> 
> On Thu, Jul 9, 2020 at 8:19 AM Inada Naoki  wrote:
>>
>> On Thu, Jul 9, 2020 at 5:46 AM M.-A. Lemburg  wrote:
>>> - the fact that the encode APIs encoding from a Unicode buffer
>>>   to a bytes object; this is an important fact, since the removal
>>>   removes access to this codec functionality for extensions
>>>
>>> - PyUnicode_AsEncodedString() is not a proper alternative, since
>>>   it requires to create a temporary PyUnicode object, which is
>>>   inefficient and wastes memory
>>
>> I wrote your points in the "Alternative Idea > Replace Py_UNICODE*
>> with Py_UCS4* "
>> section. I wrote "User can encode UCS-4 string in C without creating
>> Unicode object." in it.
>>
>> https://www.python.org/dev/peps/pep-0624/#replace-py-unicode-with-py-ucs4
>>
>> Note that the current Py_UNICODE* encoder APIs create temporary
>> PyUnicode objects.
>> They are inefficient and wastes memory now. Py_UNICODE* may be UTF-16 on some
>> platforms (e.g. Windows) and builtin codecs don't support UTF-16 input.
>>
>>
>>>
>>> - the maintenance effect mentioned in the PEP does not really
>>>   materialize, since the underlying functionality still exists
>>>   in the codecs - only access to the functionality is removed
>>>
>>
>> In the same section, I described the maintenance cost as below.
>>
>> * Other Python implementations may not have builtin codec for UCS-4.
>> * If we change the Unicode internal representation to UTF-8, we need
>> to keep UCS-4 support only for these APIs.
>>
>>> - keeping just the generic PyUnicode_Encode() API would be a
>>>   compromise
>>>
>>> - if we remove the codec specific PyUnicode_Encode*() APIs, why
>>>   are we still keeping the specisl PyUnicde_Decode*() APIs ?
>>>
>>
>> OK, I will add "Discussions" section. (I don't like "FAQ" because some 
>> question
>> are important even if it is not "frequently" asked.)
>>
>> Quick answer is:
>>
>> * They are stable ABI. (Py_UNICODE is excluded from stable ABI).
>> * Decoding from char* is more common and generic use case than encoding from
>>   Py_UNICODE*.
>> * Other Python implementations using UTF-8 as internal representation
>> can implement
>>   it easily.
>>
>> But I'm not opposite to remove it (especially for minor UTF-7 codec).
>> It is just out of scope of this PEP.
>>
>>
>>> - the deprecations were just done because the Py_UNICODE data
>>>   type was replaced by a hybrid type. Using this as an argument
>>>   for removing functionality is not really good practice, when
>>>   these are ways to continue exposing the functionality using other
>>>   data types.
>>
>> I hope the "Replace Py_UNICODE* with Py_UCS4* " section describe this.
>>
>> Regards,
>>
>> --
>> Inada Naoki  
> 
> 
> 
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/WZYG5X3MMJX6B7LWO6FXIJEORSYJSQYK/
Code of Conduct: http://python.org/psf/codeofconduct/