[Python-ideas] Pattern Matching Syntax

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


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