Hacker News new | ask | show | jobs
by wool_gather 2180 days ago
One difference I noticed from Elixir was this:

> While matching against each case clause, a name may be bound at most once, having two name patterns with coinciding names is an error.

  match data:
    case [x, x]:  # Error!
      ...
Which is a bit of a shame. This comes in handy in Elixir to say "the same value must appear at these places in the collection". I.e. for a Python tuple pattern `(x, y, x)`, `(3, 4, 5)` would not match but `(3, 4, 3)` would.

Overall, though, I think this will be a great addition to Python. Pattern matching is generally a huge boost for expressiveness and readability, in my opinion.

2 comments

Although it won't be as concise, you can use guards to emulate this feature with

    match data:
        case [x1, x2] if x1 == x2:
            ...
I agree on this being a fantastic addition to the language. I've sorely missed not having pattern matching in Python after using Rust.
I think this is a better version. It is less ambiguous and more general. The [x,x] version isn't clear if it is using `__eq__` or `is`.
Guards feel superfluous if the x, x pattern can be trivially lowered into a guard.
More vice versa. Guards look more general (being able to express not-equal, and less-than etc), so special semantics for `x,x` only seem warranted if it's very common.
Agreed they're more general. If I have a working guard implementation I can build the x, x case atop it. Meaning, the x, x case can be sugar.
Which equality will you use if it's not numbers, but something more complicated.

What if `(x, y, x)` is matched against some `(a, b, c)` where `a == c`, but not `a is c`? If yes, and you mutate `x` in the body, does it mutate `a` or does it mutate `c`?

I think at least making it an error now can leave it open to defining it later.

There's certainly no reason to use reference equality. In fact, I think equality is the wrong question: it should duplicate the match. `case (x, y, x)` should `__match__((a, b, c))` IFF `a.__match__(c)` (Not sure if that's exactly the right syntax for the Python calls, but hopefully the idea is clear.)

(Elixir has a similar operation to "pin" in a match: if you use an existing variable as the pattern, but pin it, the value must match whatever the variable is already bound to.)

> I think at least making it an error now can leave it open to defining it later.

Fair point.