To make things a little more concrete (still without actually defining the library or searching for better motivating examples), here’s a slightly rewritten example from the Scala tutorial:
def showNotification(notification: Notification) = { notification match { case Email(sender, title, _) => notify(s"You got an email from $sender with title: $title") case SMS(6060842, message) => alert(s"The number's been reconnected! You got an SMS from $number! Message: $message") case SMS(number, message) => notify(s"You got an SMS from $number! Message: $message") case VoiceRecording(name, link) => notify(s"You received a Voice Recording from $name! Click the link to hear it: $link") } } Here it is in more Python-like syntax, with a match/case statement: def show_notification(notification: Notification): match notification: case Email(sender, title, _): notify(f"You got an email from {sender} with title: {title}") case SMS(6060842, message): alert(f"The number's been reconnected! You got an SMS from {number}! Message: {message}") case SMS(number, message): notify(f"You got an SMS from {number}! Message: {message}") case VoiceRecording(name, link): notify(f"You received a Voice Recording from {name}! Click the link to hear it: {link}") And here it is without needing two new keywords, just the if try and target-or-expression unpacking syntax and a (non-magical) library: def showNotification(notification: Notification): with matching(notification) as m: if try Email, sender, title, _ ::= m: notify(f"You got an email from {sender} with title: {title}") elif try SMS, 6060842, message := m alert(f"The number's been reconnected! You got an SMS from {number}! Message: {message}") elif try SMS, number, message := m: notify(f"You got an SMS from {number}! Message: {message}") elif try VoiceRecording, name, link := m: notify(f"You received a Voice Recording from {name}! Click the link to hear it: {link}") > On Dec 31, 2019, at 14:31, Andrew Barnert via Python-ideas > <python-ideas@python.org> wrote: > > Every so often, someone suggests that Python should have a pattern matching > case statement like Scala, C#, Swift, Haskell, etc. Or they just suggest that > “Python needs algebraic data types” but end up concluding that the biggest > part Python is missing is not the types themselves, but a practical way to do > something useful with them, which basically means pattern matching. > > Anyway, with the addition of the walrus operator and @dataclass, Python is > actually a lot closer than it used to be. I believe with just two smallish > syntax features, it would be possible to do almost anything you’d ever want > in a library. > > The first is to extend unpacking assignment to target-or-expression lists. > Like this: > > x, 0, z = vec > > Just like `x, y, z = vec`, this raises a TypeError if vec isn’t Iterable, and > a ValueError if it has more or fewer than 3 elements, and otherwise, it binds > x and z to the first and third elements. But it doesn’t bind anything to the > second element; instead, it checks if that element is 0, and, if not, raises > a ValueError. > > The second is an “if try” statement, which tries an expression and runs the > body if that doesn’t raise (instead of if it’s truthy), but jumps to the next > elif/else/statement (swallowing the exception) if it does. The actual value > of the expression is discarded, but the walrus operator takes care of that: > > if try 0, y, z := vec: > # do yz plane stuff > elif try x, 0, z := vec: > # do xz plane stuff > elif try x, y, 0 := vec: > # do xy plane stuff > elif x, y, z := vec: > # do slow/imprecise/whatever 3D stuff > else: > raise TypeError(f'{vec} is not a 3-vector!') > > Alternatively, this could just be a try expression that can be used anywhere: > it’s truthy if evaluating doesn’t raise, falsey if it does. But I don’t think > it’s needed anywhere but if/elif. > > Anyway, neither of these features seems very useful on its own. (It should be > obvious how to rewrite that example as something just as readable that just > unpacks and then checks the values with normal if.) > > But I think the two of them together will allow a pure-library implementation > of pattern matching syntax that reads nicely and can do everything most other > languages do—in particular, concisely and readably pattern match and > deconstruct dataclasses (and other types with an opt-in protocol or registry, > but dataclasses would work out of the box the way Scala case classes, Swift > structs, etc. do). > > If people think either of these features is too horrible to contemplate no > matter what the potential benefits, I won’t bother working through the > details. > > But if people do want to see the details (including some good motivating > examples—I’ll go through tutorials for those other languages to find some > that don’t involve recursing into cons lists and other stuff you wouldn’t > want to do in Python…), I’ll be happy to do so, and, if it works out, turn > this into a more detailed proposal. > > And obviously, if people want to bikeshed the spelling before even seeing > what it’s good for, well, this is Python-ideas. :) > _______________________________________________ > Python-ideas mailing list -- python-ideas@python.org > To unsubscribe send an email to python-ideas-le...@python.org > https://mail.python.org/mailman3/lists/python-ideas.python.org/ > Message archived at > https://mail.python.org/archives/list/python-ideas@python.org/message/W64QFNZVAGU2EMHTLDXHRGJ7V7TYBR5R/ > Code of Conduct: http://python.org/psf/codeofconduct/
_______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/P7KKJYSRQSLLYVKYNF4R73KG6PZCTN2K/ Code of Conduct: http://python.org/psf/codeofconduct/