Comment by pansa2

Comment by pansa2 3 days ago

22 replies

The real crime is the design of Python's pattern matching in the first place:

    match status:
        case 404:
            return "Not found"

    not_found = 404
    match status:
        case not_found:
            return "Not found"
Everywhere else in the language, you can give a constant a name without changing the code's behaviour. But in this case, the two snippets are very different: the first checks for equality (`status == 404`) and the second performs an assignment (`not_found = status`).

https://x.com/brandon_rhodes/status/1360226108399099909

user453 3 days ago

That's destructuring, a feature not a bug. Same as it works in any functional language - and tremendously useful once you get the hang of it

  • pansa2 3 days ago

    At least functional languages tend to have block scope, so the latter snippet introduces a new variable that shadows `not_found` instead of mutating it.

  • b3orn 3 days ago

    No, at least in Erlang a variable is assigned once, you can then match against that variable as it can't be reassigned:

        NotFound = 404,
        case Status of
            NotFound -> "Not Found";
            _ -> "Other Status"
        end.
    
    That snippet will return "Other Status" for Status = 400. The Python equivalent of that snippet is a SyntaxError as the first case is a catch all and the rest is unreachable.
  • quotemstr 3 days ago

    Destructuring is a feature. Making it easy to confuse value capture and value reference was an error. Add single-namespace locals and you have a calamity.

  • mcdeltat 3 days ago

    Destructuring yes but you can still argue it's poorly designed. Particularly unintuitive because matching on a nested name e.g. module.CONSTANT works for matching and doesn't destructure. It's just the use of an unnested name which does destructuring.

    What Python needs is what Elixir has. A "pin" operator that forces the variable to be used as its value for matching, rather than destructuring.

  • xdennis 2 days ago

    It wouldn't be a problem is Python had block level variable scope. Having that destructuring be limited to the 'case' would be fine, but obliterating the variable outside of the match is very unexpected.

quotemstr 3 days ago

And there was a much better proposal that got rejected in favor of what we got: https://peps.python.org/pep-0642/

  • danudey 3 days ago

    The very first example there shows a match/case block where almost every single case just runs "pass" and yet every single one has a side effect. It's very difficult to read at first, difficult to understand if you're new to the syntax, and is built entirely around side effects. This might be one of the worst PEPs I've ever seen just based on that example alone.

    Fun fact: you can do the same thing with the current match/case, except that you have to put your logic in the body of the case so that it's obvious what's happening.

[removed] 3 days ago
[deleted]
almostgotcaught 3 days ago

because it's not a `switch` it's a `match` ie pattern matching...

  • pansa2 3 days ago

    Doesn't matter what it is, it shouldn't break fundamental rules of the language.

    Ruby's `case`/`in` has the same problem.

    • almostgotcaught 3 days ago

      > it shouldn't break fundamental rules of the language

      it doesn't? you simply don't understand what a match statement is.

      https://doc.rust-lang.org/book/ch19-03-pattern-syntax.html

          let num = Some(4);
      
          match num {
              Some(x) if x % 2 == 0 => println!("The number {x} is even"),
              Some(x) => println!("The number {x} is odd"),
              None => (),
          }
      
      notice that x is bound to 4.
      • tialaramex 3 days ago

        Which x? There are two in your code, one for each time you introduce a pattern Some(x) and each x has scope which of course ends when that pattern is done with

        Notice that the Python doesn't work this way, we didn't make a new variable but instead changed the existing one.

        Also, the intent in the Python was a constant, in Rust we'd give this constant an uppercase name by convention, but regardless it's a constant and so of course matching against a constant does what you expect, it can't re-bind a constant, 404 is a constant and so is `const NOT_FOUND: u16 = 404;`

      • pansa2 3 days ago

        > you simply don't understand what a match statement is

        It's "a DSL contrived to look like Python, and to be used inside of Python, but with very different semantics":

        https://discuss.python.org/t/gauging-sentiment-on-pattern-ma...

        • almostgotcaught 3 days ago

          you linked to a random detractors rant. i don't see what that has to do with whether a match statement binds a match?