Live data from Hacker News

PEP 622 – Structural Pattern Matching

python.org

121–130 of 131 posts

Re: PEP 622 – Structural Pattern Matching

#121
post #3

glad to see this! though it's a shame that the proposed `match/case` is a statement, not an expression: > "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: res…

Just as named functions replace multiline lambdas, I expect that named matcher functions (functions that consist entirely of a match where each arm is a return) will replace match expressions in python. Abstractly, I'd rather have match expressions, too, but this does fit the rest of Python better.

it's a shame :( and honestly, i think the whole "if it needs statements, it should be a named function anyway" argument is misguided (and maybe kind of a post-hoc justification of the limitations of Python lambdas). introducing a named function for something that's only going to be used in one place messes up the order (you have to keep the function in your head until it gets used) thus often making the code harder to read.

Re: PEP 622 – Structural Pattern Matching

#122
post #47
post #12

Can someone explain to me the history behind Python's aversion to switch statements? I get Python is opinionated and I'm not trying to start a language war, it was just never clear to me why the `if ... elif` pattern was the preferred idiom.

Case statements are an anti-pattern. The proper way to implement that design pattern is using either dispatch dictionaries or plain-old polymorphism.

I see. Are you able to provide an example?

Re: PEP 622 – Structural Pattern Matching

#123
post #6

Very interesting. This PEP is still in draft state, but I am interested to see how the community will react. For me, I have a few thoughts: 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 readabil…

I have a visceral dislike of pattern matching. Lisp shows just how much people will abuse it in real-world production codebases. It becomes impossible to understand even simple logic without comments. I’d link to some examples, but I’m on mobile; suffice to say, pull up the emacs codebase and read through some of the more advanced modules like edebug.el. I’m not certain that one uses pattern matching, but it’s a perf…

Can you provide any examples?

Re: PEP 622 – Structural Pattern Matching

#124
post #66

Earlier quoted context omitted.

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 mat…

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`.

Re: PEP 622 – Structural Pattern Matching

#125
post #117

Earlier quoted context omitted.

I have a visceral dislike of pattern matching. Lisp shows just how much people will abuse it in real-world production codebases. It becomes impossible to understand even simple logic without comments. I’d link to some examples, but I’m on mobile; suffice to say, pull up the emacs codebase and read through some of the more advanced modules like edebug.el. I’m not certain that one uses pattern matching, but it’s a perf…

People use pattern matching all the time in ML or rust or haskell or Scala or Elm. It's totally uncontroversial there, and it's helpful to readability, not harmful. Erlang and Elixir also show it works in untyped languages pretty well.

Python is famous for its readability. ML, rust, and Haskell are famous for their unreadability.

Re: PEP 622 – Structural Pattern Matching

#126
I'm excited, but it seems like setting names by default is very odd. Quite a bit of the PEP is dedicated to the odd situations created by "case x" actually setting x rather than reading x ("case .x" would read x). Wouldn't this be a natural place for := ? So you would do:

  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.

Re: PEP 622 – Structural Pattern Matching

#127

I'm excited, but it seems like setting names by default is very odd. Quite a bit of the PEP is dedicated to the odd situations created by "case x" actually setting x rather than reading x ("case .x" would read x). Wouldn't this be a natural place for := ? So you would do: 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 p…

With pattern matching you normally want bindings, at least local to the match construct (that the PEP proposes bindings with normal Python function scope, rather than local to the construct has plusses and minuses), so creating extra verbosity for bindings is complicating the normal case.

Re: PEP 622 – Structural Pattern Matching

#128
post #47

Earlier quoted context omitted.

Case statements are an anti-pattern. The proper way to implement that design pattern is using either dispatch dictionaries or plain-old polymorphism.

I see. Are you able to provide an example?

Suppose you are dispatching on token types. You could write something like this:

    handlers = {'start' : handle_start, 'jump' : handle_jump, 'end' : handle_end, ...}
    for tok, arg in tokens:
        if tok not in handlers:
            raise ValueError('Wrong token type, must be any of %s.' % ', '.join(handlers))
        handlers[tok](arg)

Re: PEP 622 – Structural Pattern Matching

#129

Earlier quoted context omitted.

I see. Are you able to provide an example?

Suppose you are dispatching on token types. You could write something like this: handlers = {'start' : handle_start, 'jump' : handle_jump, 'end' : handle_end, ...} for tok, arg in tokens: if tok not in handlers: raise ValueError('Wrong token type, must be any of %s.' % ', '.join(handlers)) handlers[tok](arg)

I see, I do follow that design pattern for larger switch statements or where the dictionary had to be dynamically populated (even in non-Python languages) but I hadn't considered using it for smaller switch statements as well.

Thank you for the example.

Re: PEP 622 – Structural Pattern Matching

#130
post #87

Earlier quoted context omitted.

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.
Post reply on HN