[Python-ideas] Pattern Matching Syntax

Joao S. O. Bueno jsbueno at python.org.br
Thu May 3 09:16:40 EDT 2018


(sorry - my aboe message is about using a dictionary - the "=>" weird
tokens should j=be just plain ":" -
the point is that Python açready has syntax to do what is asked)

On 3 May 2018 at 10:15, Joao S. O. Bueno <jsbueno at python.org.br> wrote:
> What about instead of
>
> number = match x:
>     1 => "one"
>     2 => "two"
>     3 => "three"
>     10 => "ten"
>     _ => "anything"
>
> number = {
>     1 => "one"
>     2 => "two"
>     3 => "three"
>     10 => "ten"
>     }.get(x,  "anything")
>
> No magic syntax with blocks starting inside an assignment, just to start with.
>
>
> On 3 May 2018 at 09:41, Robert Roskam <raiderrobert at gmail.com> wrote:
>> Hi Everyone,
>>
>> Never posted in here before, so I hope that I'm not violating any particular
>> procedure for intros or something.
>>
>> Over time, there have been various switch or match statement proposal; some
>> that have gotten as far as PEPs:
>>
>> 2001 Nov - https://www.python.org/dev/peps/pep-0275/
>>
>> 2006 Jun - https://www.python.org/dev/peps/pep-3103/
>>
>> 2014 Apr -
>> https://groups.google.com/d/msg/python-ideas/J5O562NKQMY/DrMHwncrmIIJ
>>
>> 2016 May -
>> https://groups.google.com/d/msg/python-ideas/aninkpPpEAw/wCQ1IH5mAQAJ
>>
>> However, I don't see that the conversation ever really resolved, so I'd like
>> restart the conversation on some kind of pattern matching syntax in Python.
>>
>> The main objections I've seen are in the following buckets:
>>
>> One--and Preferably Only One--Obvious Way. Basically, we have if/elif and
>> that's all we need, so this is syntactical sugar bloat. I'd submit that
>> there are specific cases where this kind of syntax would be the obviously
>> correct way to do something
>> Specific Syntax Objections. There have been several specific objections that
>> usually come down to "unreadable" or "ugly", which are subjective statements
>> that don't really bring any good way to continue the discussion in a
>> productive manner.
>>
>> I cannot handle all syntax objections ahead of time, but I can handle the
>> "only way" objection. At high level, pattern matching provides similar
>> syntactical sugar to list comprehensions. We could argue that they are
>> unnecessary since we have for loops. But more importantly, pattern matching
>> is powerful for what it restricts you to. More specifically:
>>
>> Assignment. Many of the implementations offer the ability to immediately
>> assign the value from the matching pattern. However, assignment is prevented
>> in the middle of all of the patterns, which is possible in if/elif.
>> No Fall Through. Once a pattern is matched, there's no way to break to try
>> another branch. Prevents having to look at multiple cases to figure out how
>> something resolved. If/elif can have this happen, of course, but even more
>> confusing sometimes breaks will be mixed with returns or other control
>> flows, which makes figuring how large if/elifs are resolved.
>> Automatic Unpacking. Some implementations offer the ability unpack a
>> dictionary equivalent automatically into keys or select ranges of values
>> like slicing. Compared to if/elif, this is tremendously more DRY than doing
>> the "does the key exists?" and then "what is that keys value?"
>> Guards. Often times you can embed another check to go along with the simple
>> pattern matching. Absolutely possible with if/elif, but crucially are
>> implementations generally happen after the pattern check. Again, keeps code
>> DRY and improves readability.
>>
>> I figured maybe a good way to continue the discussion is to offer a
>> straw-man example syntax:
>>
>> # Simple pattern matching
>> x = 1
>>
>> number = match x:
>>     1 => "one"
>>     2 => "two"
>>     3 => "three"
>>     10 => "ten"
>>     _ => "anything"
>>
>> print(number)  # one
>>
>>
>> # Final Pattern that matches anything
>> x = 3
>>
>> number = match x:
>>     1 => "one"
>>     2 => "two"
>>     _ => "anything"
>>
>> print(number) # anything
>>
>>
>> # Pattern matching without any match returns None
>> number = match x:
>>     1 => "one"
>>     2 => "two"
>>
>> print(number)  # None
>>
>>
>> # Pattern matching with guards
>> x = 'three'
>>
>> number = match x:
>>     1 => "one"
>>     y if y is str => f'The string is {y}'
>>     _ => "anything"
>>
>> print(number)  # The string is three
>>
>>
>> # Pattern matching with multiple values
>> x = 1
>>
>> number = match x:
>>     1, 2, 3, 4 => "one to four"
>>     _ => "anything"
>>
>> print(number)  # one to four
>>
>>
>> # Pattern matching with types
>> x = 1.
>>
>> number = match x:
>>     x:int => f'{x} is a int'
>>     x:float => f'{x} is a float'
>>     x:str => f'{x} is a string'
>>
>> print(number)  # x is a float
>>
>>
>> # Supports destructuring dicts
>>
>> x = {'foo': 1}
>>
>> number = match x:
>>     {'foo': 1} => "foo is 1"
>>     _ => "anything"
>>
>> print(number)  # foo is 1
>>
>>
>> # Supports binding with destructuring dicts
>>
>> x = {'foo': 1, 'bar': 2}
>>
>> number = match x:
>>     {'foo': y} => f'got foo {y}'
>>     {'bar': z} => f'got bar {z}'
>>     {'foo': y, 'bar': z} => f'got foo {y} and bar {z}'
>>     _ => "anything"
>>
>> print(number)  # got foo 1 and bar 2
>>
>>
>> # Supports destructuring other types too
>>
>> class Point():
>>     def __init__(self, x, y):
>>         self.x = x
>>         self.y = y
>>
>> point = Point(1,2)
>>
>> number = match point:
>>     Point(x,y) => f'point has an x of {x} and y of {y}'
>>     _ => "anything"
>>
>> print(number)  # point has an x of 1 and y of 2
>>
>>
>> As a continued defense for this specific syntax choixe, lets see how two
>> other languages with this feature handle it. I'm going to try to offer as
>> nearly as possible similar examples.
>>
>> Scala https://docs.scala-lang.org/tour/pattern-matching.html
>>
>> val x: Int = 1
>>
>> def makeMatch(x:  Any) = x match {
>>  case 1 => "one"
>>  case 2 => "two"
>>  case _ => "anything"
>> }
>>
>> val number = makeMatch(x)
>>
>> Rust https://doc.rust-lang.org/1.5.0/book/match.html
>>
>> let x = 1;
>>
>> let number = match x {
>>     1 => "one",
>>     2 => "two",
>>     _ => "anything",
>> }
>>
>> And for the sake of completeness, here are other languages with similar
>> syntax features and their associated documentation
>>
>> F#
>> https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/pattern-matching
>>
>> Elixir https://elixir-lang.org/getting-started/case-cond-and-if.html
>>
>> Clojure https://github.com/clojure/core.match/wiki/Basic-usage
>>
>> JavaScript (ES2018?) https://github.com/tc39/proposal-pattern-matching
>>
>> Haskell https://en.wikibooks.org/wiki/Haskell/Pattern_matching
>>
>> Swifthttps://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Patterns.html
>>
>>
>>
>>
>>
>>
>>
>> _______________________________________________
>> Python-ideas mailing list
>> Python-ideas at python.org
>> https://mail.python.org/mailman/listinfo/python-ideas
>> Code of Conduct: http://python.org/psf/codeofconduct/
>>


More information about the Python-ideas mailing list