Hi Caleb,
I will only answer to the second part, as the wildcard issue has
been brought up and discussed time and again, and the `np`
analogue is quite a stretch and far-fetched, really.
One thing that stood out a bit to me as I feel to have seen it a
couple of times is the question of intuition, so I will add a few
more general thoughts to that...
> [...] but it seems quite unintuitive to me [...]
> [...] don't necessarily make it intuitively clear [...]
Intuition (or lack thereof) has already been brought forward
as an argument a couple of times. I would just like to briefly
point out that there is no such thing as universal intuition in
the field of programming. We all have different training,
skills, preferences and experiences, which make up what
we call 'intuition'. But what is intuitive is usually something
completely different to C-programmer than to a Haskell- or
Lisp-Programmer, say. 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.
As for beginners, virtually every part of programming is
unintuitive at first. Even something innocuous-looking like
assignment is often reason for confusion because `3 + 4 = x`
would probably be more 'intuitive'. But there is good reason
with regards to the bigger picture to stick to `x = 3 + 4`.
A Python-programmer (at any level) not familiar with pattern
matching will most likely not understand all subtlety of the
syntax---but this is alos true of features like `async` or the
`/` in parameters, say. I would argue, though, that the clear
choice of keywords allow anyone to quickly look pattern
matching up and get informed on what it does. So, we do
not need to come with something that is entirely 'intuitive'
and 'self-evident'. But by sticking to common convention
like `_` as wildcard, we can help quickly build the correct
intuition.
In your examples, for instance, it is perfectly obvious to me
that you cannot directly assign to attributes and it would in
fact look very weird to my eyes if you could. Your use case
is quite similar to initialisers and you are arguing that you
would like being able to write:
```
class Point:
def __init__(self, self.x, self.y):
pass
```
rather than the more verbose:
```
class Point:
def __init__(self, x, y):
self.x, self.y = x, y
```
I do not think that this would be a good idea for either
parameters or patterns. After all, pattern matching is
*not* assignment, even though it is related to it, of
course.
Kind regards,
Tobias
Quoting Caleb Donovick <donovick@cs.stanford.edu>:
Adding this feature would be a giant quality of life improvement for me and I really hope it succeeds. So I have been trying to keep up on the debate in this and related thread.
While I do want this feature, I agree with a lot of the issues people are raising.
First I agree that _ should not be the wildcard symbol. Or rather the hobgoblins in my mind think that if _ is to be the wildcard symbol it would be more consistent with assignment if it was bound to the last value it was matched with (as should other repeated identifiers) e.g.,
match pt: case (x, _, _): assert _ == pt[2]
I understand the authors rationalize the decision based on conventions with the gettext module. I find these arguments very unconvincing. It's like saying the identifier np should be forbidden from appearing in cases because it's frequently used as the name of numpy. If there is to be a wildcard symbol (that does not bind and is repeatable) it should not be a valid identifier.
Second, the distinction between a capture and constant value pattern should be more explicit. I don't have any great insight into the color of the shed beyond the numerous suggestions already made (name=, ?name, etc...), but it seems quite unintuitive to me that I can't capture into a namespace nor match a constant without a namespace. It is also unclear to me why it would be so terrible to add a new token or abuse an existing one.
> Honestly, it doesn't help the case for `?` that it's been proposed as a mark for both capture patterns and value patterns (by different people, obviously :-).
I agree that most of the proposed sheds don't necessarily make it intuitively clear what is a capture variable vs what is a constant. However they do give the programmer the ability to choose.
For example if I want to modify the motivating example from the PEP slightly to copy attributes from one point to another I can't express it concisely:
def update_point_3d(p: Point3d, pt): match pt: case (x, y): p.x, p.y = x, y case Point2d(x, y): p.x, p.y = x, y ...
(Okay I could have just called the original make_point_3d and unpacked the results but it would require the creation of an unnecessary temporary.)
However if the capture was explicit and any valid target could be used as a capture variable then I could express this cleanly:
def update_point_3d(p: Point3d, pt): match pt: case (p.x=, p.y=): pass case Point2d(p.x=, p.y=): pass ...
- Caleb Donovick