by kragniz on 6/24/20, 12:20 PM with 122 comments
by justusw on 6/24/20, 12:45 PM
1) This is really close to Erlang/Elixir pattern matching and will make fail-early code much easier to write and easier to reason about.
2) match/case means double indentation, which I see they reasoned about later in the "Rejected ideas". Might have a negative impact on readability.
3) Match is an already used word (as acknowledged by the authors), but I think this could have been a good case for actually using hard syntax. For me, perhaps because I'm used to it, Elixir's "{a, b, c} = {:hello, "world", 42}" just makes sense.
4) I hope there won't be a big flame-war debacle like with :=
5) And then finally there is the question of: "It's cool, but do we really need it? And will it increase the surprise factor?" And here I'm not sure. And again, this was the concern with the new assignment expression. The assignment expression is legitimately useful in some use cases (no more silly while True), but it might reduce the learnability of Python. Python is often used as an introductory programming language, so the impact would be that curricula need to be adjust or beginner programmers will encounter some surprising code along the road.
I can't say this is a good or bad proposal, I want to see what other opinions are out there, and what kind of projects out there in the world would really benefit from syntax like this.
by mdrachuk on 6/24/20, 1:25 PM
Seems like it doesn’t create instances when you’re doing
Node(children=[Leaf(value="("), Node(), Leaf(value=")")])
instead:1. Node means "is instance of Node".
2. Everything in between () is "has an attribute with value".
3. List means "the attribute should be treated as a tuple of".. etc..
Very confusing, this definitely needs another syntax, because both newcomers and experienced devs will be prone to read it as plain `==`, since that's how enums and primitives will be working.
This syntax goes against Zen: It’s implicit -- when using match case expressions don't mean what they regularly mean. It’s complicated -- basically it’s another language (like regex) which is injected into Python.
I’m a big believer in this feature, it just needs some other syntax. Using {} instead of () makes it a lot better. Now no way to confuse it with simple equality.
match node:
case Node{children=[{Leaf{value="(", Node{}, ...}}
by uryga on 6/24/20, 12:34 PM
> "We propose the match syntax to be a statement, not an expression. Although in many languages it is an expression, being a statement better suits the general logic of Python syntax."
no matching in lambdas unless those get overhauled too :(
instead, let's get excited for a whole bunch of this:
match x
case A:
result = 'foo'
case B:
result = 'bar'
(i guess i'm a little salty...)by MattConfluence on 6/24/20, 3:29 PM
If you're curious about why this is so useful, and reading the (quite dry) PEP isn't your thing, I would heartily recommend playing with Elixir for a few hours. Pattern matching is a core feature of the language, you won't be able to avoid using it. The language is more Ruby-like than Python-like, but Python programmers should still have an easy time grokking it. When I was getting started I used Exercism [1] to have some simple tasks to solve.
by sicromoft on 6/24/20, 11:52 PM
by mkl on 6/24/20, 12:36 PM
That's interesting. Python 3.6 had "async" and "await" as soft keywords, before they became reserved keywords in 3.7 [1]. However, soft keywords have just been added to Python more generally [2], so aren't such a special case anymore.
[1] https://www.python.org/dev/peps/pep-0530/
[2] https://github.com/python/cpython/pull/20370, https://github.com/python/cpython/pull/20370/files
by aparmentier on 6/24/20, 4:37 PM
a * b == "a times b"
a * * b == "a to the power of b"
f(* a) == "call f by flattening the sequence a into args of f"
f(* * a) == "call f by flattening the map a into key value args for f"
[* a] == "match a sequence with 0 or more elements, call them a"
Am I missing something? I know these all occur in different contexts, still the general rule seems to be "* either means something multiplication-y, or means 'having something to do with a sequence' -- depends on the context". It's getting to be a bit much, no?
Note: HN is making me put spaces between * to avoid interpretation as italics.
by BiteCode_dev on 6/24/20, 2:47 PM
Unpacking was huge 10 years ago, but nowaday even JS has object destructuring, so python was lagging behind.
It feels like they really spent a lot of time in designing this: Python has clearly not be made for that, and they have to balance legacy design with the new feature.
I think the matching is a success in that regard, and the __match__ method is a great idea. The guards will be handy, while the '_' convention is finally something official. And thanks god for not doing the whole async/await debacle again. Breaking people's code is bad.
On the other hand, I understand the need for @sealed, but this is the kind of thing that shows that Python was not designed with type hints from the begining. Haskell devs must have a laught right now.
We can thank Guido for the PEG parser in 3.9 whichs allows him to co-author this as well.
I expect some ajustments to be made, because we will discover edge cases and performance issues, for sure. Maybe they'll change their mind on generalized unpacking: I do wish to be able to use that for dicts without having to create a whole block.
But all in all, I believe it will be the killer feature of 3.10, and while I didn't see the need to move from 3.7, walrus or not, 3.10 will be my next target for upgrade.
by csantini on 6/24/20, 1:58 PM
https://github.com/santinic/pampy
Even match on Point(x, y, _)
by sitkack on 6/24/20, 1:41 PM
by whalesalad on 6/25/20, 2:01 AM
My biggest concern is the class matching syntax. I feel like that would be much better deferred to a lambda style function or similar. The syntax matches instantiating a new class instance exactly, which seems like it could cause a lot of problems for tools that read and manipulate syntax.
by hnlmorg on 6/24/20, 1:16 PM
by jjice on 6/24/20, 2:56 PM
by henryiii on 6/25/20, 6:38 PM
case x := _
to match and assign to x. "_" would always be the matcher. You always have access to the original item that the match was made on, so pulling out the matched items is often not needed, AFAICT. This would be explicit, and not too surprising. Then the whole dotted names part can be dropped - it works like normal Python at that point.The PEP already suggests this for capturing parts of the match, why not just use it for all saved matches? It's more verbose, but consistent, with fewer caveats, and not always needed.
Disclaimer: My languages don't happen to include one with good pattern matching, so I'm not strongly familiar with it.
by lincolnq on 6/24/20, 1:27 PM
One subtle thing which I noticed is the distinction between class patterns and name patterns (bindings). In particular, it is possibly confusing that the code `case Point:` matches anything and binds it to the value Point, whereas `case Point():` checks if the thing is an instance of Point and doesn’t bind anything.
by Spiritus on 6/24/20, 12:33 PM
With that said, this has been suggested and discussed many times in the past. I imagine this will be as controversial as the walrus operator[1] was.
by Narann on 6/24/20, 12:57 PM
Is this will create a second Node instance and compare it to node?
If so, is it not less efficient performance wise than it's "counterpart" isinstance() + properties comparison?
If this method is less efficient, it could be confusing, specially for newcomer.
Am I missing something.
by fulafel on 6/25/20, 5:42 AM
by vslira on 6/24/20, 3:06 PM
[1] Yes I know coconut-lang is a thing, but I didn't want to introduce something that looks a lot like Python but isn't in our codebase
by loa_in_ on 6/25/20, 8:42 AM
>case True: ... case 1: ...
From practical perspective this is great, but I can imagine many cases where one could want to differentiate between those.
On one hand the number usually can be nested inside a structure and matching on == is more flexible. On the other hand matching on 'is' is still letting users relax this behaviour and allows matching on type of primitives as well.
by xiaodai on 6/24/20, 11:30 PM
by blondin on 6/24/20, 12:55 PM
by creativecupcak3 on 6/24/20, 3:15 PM
by macintux on 6/25/20, 2:55 AM
Python 3 eliminated the ability to match on tuples in function heads.
For loops can match on tuples, but lambda headers can’t.
As an Erlang fan, it’s maddening.
by fnord77 on 6/25/20, 4:48 AM