News for hackers. Stuff that matters.
Re:Pattern matching accepted for Python by TrianguloY on Tuesday February 09, 2021 @03:50PM (#26082214)
Can't wait to see all the errors and questions when users start using this for the missing switch statement, and not realizing it doesn't work for non-dotted constants.

Because if I didn't misunderstood, this is not correct, is it?

  NOT_FOUND = 404
  OK = 200

  match getCode():
      case NOT_FOUND:
          return default()
      case OK:
          return response()
Re:Pattern matching accepted for Python by AlexandrB on Tuesday February 09, 2021 @03:57PM (#26082297)
Yup, that's what the PEP seems to suggest.

This along with mutable default values is going to be one of the nastier Python warts.

Re:Pattern matching accepted for Python by toxik on Tuesday February 09, 2021 @04:02PM (#26082342)
Not to mention that expressions after the case keyword have completely different semantics from expressions ANYWHERE else. a | b is not the bitwise or of a with b.
Re:Pattern matching accepted for Python by amirkdv on Wednesday February 10, 2021 @12:00AM (#26085886)
This part is truly strange. This example from the tutorial drove it home for me:

    match event.get():
        case Click(position=(x, y)):
            handle_click_at(x, y)
        case KeyPress(key_name="Q") | Quit():
            game.quit()
where `Click(position=(x, y))` is not at all what one would expect.

What I still don't understand is: does the new syntax magically do this to a user-defined class? i.e. if I say

    foo = Click(position=(x, y))
vs

    ...
    case Click(position=(x, y))
those identical expressions, for the same value of Click, have widely different semantics?

edit: typo fix

Re:Pattern matching accepted for Python by bobbylarrybobby on Wednesday February 10, 2021 @09:54PM (#26097727)
You are (sadly) correct. The latter example checks that the type of `event.get()` is a Click, then that it has a `.position` attribute that be restructured into a two-element tuple `(x,y)`. It's equivalent to `ev = event.get(); if isinstance(ev, Click): (x,y) = ev.position`
Re:Pattern matching accepted for Python by vitus on Tuesday February 09, 2021 @04:07PM (#26082387)
You can already define __or__ to do whatever you want!

This is already special-cased in the standard library for, say, set union (where admittedly the concept is more similar to bitwise or).

Re:Pattern matching accepted for Python by toxik on Tuesday February 09, 2021 @04:09PM (#26082413)
... except in case expressions

Thanks for proving my point though!

Re:Pattern matching accepted for Python by vitus on Tuesday February 09, 2021 @03:59PM (#26082323)
Correct.

> Patterns may use named constants. These must be dotted names to prevent them from being interpreted as capture variable:

NOT_FOUND would always match as a capture variable, so you'd always return default().

I fully expect this to be covered by linters, but not with further language support.

Re:Pattern matching accepted for Python by mvolfik on Tuesday February 09, 2021 @04:51PM (#26082826)
yeah, I would also expect the linters to catch this. has some way to allow use of non-dotted constants been considered? something like window.global_variable in JavaScript? Or would I need to do something like this:?

  NOT_FOUND = 404
  m = {"NOT_FOUND": NOT_FOUND}
  match value:
    case m["NOT_FOUND"]:
      pass
Re:Pattern matching accepted for Python by chriswarbo on Tuesday February 09, 2021 @07:04PM (#26084244)
You can do

    NOT_FOUND = 404
    match value:
      case v if v == NOT_FOUND:
        pass
On its own this is a convoluted alternative to `if`, but it can be useful when we have lots of patterns.

Alternatively, we can avoid using a separate `v` variable and just use `value` directly:

    NOT_FOUND = 404
    match value:
      case _ if value == NOT_FOUND:
        pass
We can even match on a trivial value, and do all of the interesting checks using guards:

    NOT_FOUND = 404
    match None:
      case _ if value == NOT_FOUND:
        pass
This latter form acts like Lisp's `cond`, and I've used it a few times in Scala, e.g.

    () match {
      case _ if foo >  bar => ...
      case _ if foo <  bar => ...
      case _ if foo == bar => ...
    }
Re:Pattern matching accepted for Python by hyperbovine on Wednesday February 10, 2021 @05:01AM (#26087359)
But all of these alternatives are strictly less intuitive than the original expression. A big reason why I got into Python was because it’s the language that can be “read by anyone”, even those who do not know Python. This latest PEP, coming on the heels of several others like it, shows how alarmingly far from the ideal we’ve come since 2.7.
Re:Pattern matching accepted for Python by chriswarbo on Wednesday February 10, 2021 @06:30AM (#26087910)
> But all of these alternatives are strictly less intuitive than the original expression.

I agree; I was just trying to show how pattern guards work. I would only resort to pattern guards if I need a `cond` (like my last example), or on a few cases of a more 'natural' pattern match, e.g.

    match foo():
      case OK(msg):
        return success(msg)
      case NotFound(_) if isQuery:
        return success("No results matched query")
      case NotFound(msg):
        return failure(msg)
      ...
If I were to implement your original example (i.e. 'which of these constants do I have?'), I'd probably still go with a "dictionary dispatch" (especially since it's an expression, so it works in lambdas, etc.):

    return {
      NOT_FOUND: default,
      OK: response,
    }[getCode()]()
Re:Pattern matching accepted for Python by pansa2 on Wednesday February 10, 2021 @05:29AM (#26087524)
> A big reason why I got into Python was because it’s the language that can be “read by anyone”, even those who do not know Python.

Yes! For the first 2 decades of its life, people loved Python because it was like “executable pseudocode”. Unfortunately over the last 5-10 years it seems to have given up on that idea, instead becoming more and more like “whitespace-sensitive C++”.

Re:Pattern matching accepted for Python by TrianguloY on Tuesday February 09, 2021 @05:16PM (#26083133)
I may be wrong, but after reading the grammar I think your example is a syntax error. You can't access an element! A pattern syntax is completely different to a normal expression, and there is apparently no array access.
Re:Pattern matching accepted for Python by mvolfik on Tuesday February 09, 2021 @05:31PM (#26083319)
hmm, so I would need to use some namespace class https://docs.python.org/3.8/library/types.html#types.SimpleN...
Re:Pattern matching accepted for Python by bjoli on Wednesday February 10, 2021 @12:45PM (#26092367)
Well, of course. It is a pattern matcher. case NOT_FOUND: is a pattern that matches anything and binds it to NOT_FOUND. If you want to match the content of a variable you need to signal that in some way. In scheme that usually means unquote:

    (define not-found 404)
    (match status
      (,not-found (do-stuff))
      (else (display "you might believe this is an else clause, but it actually just matches everything and binds it to else")))
Re:Pattern matching accepted for Python by thehesiod on Tuesday February 09, 2021 @10:08PM (#26085339)
plus the distinction of using dotted constants makes no sense, that can just mean a variable in another module