On 24.06.2020 16:27, M.-A. Lemburg wrote: > Wow, so 19 years after PEP 275, we are indeed getting a switch > statement. Nice :-) > > Something which struck me as odd when first scanning through the PEP > is the default case compared to other Python block statements: > > match something: > case 0 | 1 | 2: > print("Small number") > case [] | [_]: > print("A short sequence") > case str() | bytes(): > print("Something string-like") > case _: > print("Something else") > > rather than what a Pythonista would probably expect: > > match something: > case 0 | 1 | 2: > print("Small number") > case [] | [_]: > print("A short sequence") > case str() | bytes(): > print("Something string-like") > else: > print("Something else") > > Was there a reason for using a special value "_" as match-all value ? > I couldn't find any explanation for this in the PEP.
To clarify: The Python compiler could turn the "else:" into what "case _:" would produce. The syntax would just look more intuitive, IMO. The question was not about using "_" as match-all in general. > Cheers. > > > > On 23.06.2020 18:01, Guido van Rossum wrote: >> I'm happy to present a new PEP for the python-dev community to review. >> This is joint work with Brandt Bucher, Tobias Kohn, Ivan Levkivskyi and >> Talin. >> >> Many people have thought about extending Python with a form of pattern >> matching similar to that found in Scala, Rust, F#, Haskell and other >> languages with a functional flavor. The topic has come up regularly on >> python-ideas (most recently yesterday :-). >> >> I'll mostly let the PEP speak for itself: >> - Published: https://www.python.org/dev/peps/pep-0622/ (*) >> - Source: https://github.com/python/peps/blob/master/pep-0622.rst >> >> (*) The published version will hopefully be available soon. >> >> I want to clarify that the design space for such a match statement is >> enormous. For many key decisions the authors have clashed, in some cases >> we have gone back and forth several times, and a few uncomfortable >> compromises were struck. It is quite possible that some major design >> decisions will have to be revisited before this PEP can be accepted. >> Nevertheless, we're happy with the current proposal, and we have >> provided ample discussion in the PEP under the headings of Rejected >> Ideas and Deferred Ideas. Please read those before proposing changes! >> >> I'd like to end with the contents of the README of the repo where we've >> worked on the draft, which is shorter and gives a gentler introduction >> than the PEP itself: >> >> >> # Pattern Matching >> >> This repo contains a draft PEP proposing a `match` statement. >> >> Origins >> ------- >> >> The work has several origins: >> >> - Many statically compiled languages (especially functional ones) have >> a `match` expression, for example >> >> [Scala](http://www.scala-lang.org/files/archive/spec/2.11/08-pattern-matching.html), >> [Rust](https://doc.rust-lang.org/reference/expressions/match-expr.html), >> >> [F#](https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/pattern-matching); >> - Several extensive discussions on python-ideas, culminating in a >> summarizing >> [blog >> post](https://tobiaskohn.ch/index.php/2018/09/18/pattern-matching-syntax-in-python/) >> by Tobias Kohn; >> - An independently developed [draft >> >> PEP](https://github.com/ilevkivskyi/peps/blob/pattern-matching/pep-9999.rst) >> by Ivan Levkivskyi. >> >> Implementation >> -------------- >> >> A full reference implementation written by Brandt Bucher is available >> as a [fork]((https://github.com/brandtbucher/cpython/tree/patma)) of >> the CPython repo. This is readily converted to a [pull >> request](https://github.com/brandtbucher/cpython/pull/2)). >> >> Examples >> -------- >> >> Some [example >> code](https://github.com/gvanrossum/patma/tree/master/examples/) is >> available from this repo. >> >> Tutorial >> -------- >> >> A `match` statement takes an expression and compares it to successive >> patterns given as one or more `case` blocks. This is superficially >> similar to a `switch` statement in C, Java or JavaScript (an many >> other languages), but much more powerful. >> >> The simplest form compares a target value against one or more literals: >> >> ```py >> def http_error(status): >> match status: >> case 400: >> return "Bad request" >> case 401: >> return "Unauthorized" >> case 403: >> return "Forbidden" >> case 404: >> return "Not found" >> case 418: >> return "I'm a teapot" >> case _: >> return "Something else" >> ``` >> >> Note the last block: the "variable name" `_` acts as a *wildcard* and >> never fails to match. >> >> You can combine several literals in a single pattern using `|` ("or"): >> >> ```py >> case 401|403|404: >> return "Not allowed" >> ``` >> >> Patterns can look like unpacking assignments, and can be used to bind >> variables: >> >> ```py >> # The target is an (x, y) tuple >> match point: >> case (0, 0): >> print("Origin") >> case (0, y): >> print(f"Y={y}") >> case (x, 0): >> print(f"X={x}") >> case (x, y): >> print(f"X={x}, Y={y}") >> case _: >> raise ValueError("Not a point") >> ``` >> >> Study that one carefully! The first pattern has two literals, and can >> be thought of as an extension of the literal pattern shown above. But >> the next two patterns combine a literal and a variable, and the >> variable is *extracted* from the target value (`point`). The fourth >> pattern is a double extraction, which makes it conceptually similar to >> the unpacking assignment `(x, y) = point`. >> >> If you are using classes to structure your data (e.g. data classes) >> you can use the class name followed by an argument list resembling a >> constructor, but with the ability to extract variables: >> >> ```py >> from dataclasses import dataclass >> >> @dataclass >> class Point: >> x: int >> y: int >> >> def whereis(point): >> match point: >> case Point(0, 0): >> print("Origin") >> case Point(0, y): >> print(f"Y={y}") >> case Point(x, 0): >> print(f"X={x}") >> case Point(): >> print("Somewhere else") >> case _: >> print("Not a point") >> ``` >> >> We can use keyword parameters too. The following patterns are all >> equivalent (and all bind the `y` attribute to the `var` variable): >> >> ```py >> Point(1, var) >> Point(1, y=var) >> Point(x=1, y=var) >> Point(y=var, x=1) >> ``` >> >> Patterns can be arbitrarily nested. For example, if we have a short >> list of points, we could match it like this: >> >> ```py >> match points: >> case []: >> print("No points") >> case [Point(0, 0)]: >> print("The origin") >> case [Point(x, y)]: >> print(f"Single point {x}, {y}") >> case [Point(0, y1), Point(0, y2)]: >> print(f"Two on the Y axis at {y1}, {y2}") >> case _: >> print("Something else") >> ``` >> >> We can add an `if` clause to a pattern, known as a "guard". If the >> guard is false, `match` goes on to try the next `case` block. Note >> that variable extraction happens before the guard is evaluated: >> >> ```py >> match point: >> case Point(x, y) if x == y: >> print(f"Y=X at {x}") >> case Point(x, y): >> print(f"Not on the diagonal") >> ``` >> >> Several other key features: >> >> - Like unpacking assignments, tuple and list patterns have exactly the >> same meaning and actually match arbitrary sequences. An important >> exception is that they don't match iterators or strings. >> (Technically, the target must be an instance of >> `collections.abc.Sequence`.) >> >> - Sequence patterns support wildcards: `[x, y, *rest]` and `(x, y, >> *rest)` work similar to wildcards in unpacking assignments. The >> name after `*` may also be `_`, so `(x, y, *_)` matches a sequence >> of at least two items without binding the remaining items. >> >> - Mapping patterns: `{"bandwidth": b, "latency": l}` extracts the >> `"bandwidth"` and `"latency"` values from a dict. Unlike sequence >> patterns, extra keys are ignored. A wildcard `**rest` is also >> supported. (But `**_` would be redundant, so it not allowed.) >> >> - Subpatterns may be extracted using the walrus (`:=`) operator: >> >> ```py >> case (Point(x1, y1), p2 := Point(x2, y2)): ... >> ``` >> >> - Patterns may use named constants. These must be dotted names; a >> single name can be made into a constant value by prefixing it with a >> dot to prevent it from being interpreted as a variable extraction: >> >> ```py >> RED, GREEN, BLUE = 0, 1, 2 >> >> match color: >> case .RED: >> print("I see red!") >> case .GREEN: >> print("Grass is green") >> case .BLUE: >> print("I'm feeling the blues :(") >> ``` >> >> - Classes can customize how they are matched by defining a >> `__match__()` method. >> Read the >> [PEP](https://github.com/python/peps/blob/master/pep-0622.rst#runtime-specification) >> for details. >> >> >> >> -- >> --Guido van Rossum (python.org/~guido <http://python.org/~guido>) >> /Pronouns: he/him //(why is my pronoun here?)/ >> <http://feministing.com/2015/02/03/how-using-they-as-a-singular-pronoun-can-change-the-world/> >> >> _______________________________________________ >> Python-Dev mailing list -- python-dev@python.org >> To unsubscribe send an email to python-dev-le...@python.org >> https://mail.python.org/mailman3/lists/python-dev.python.org/ >> Message archived at >> https://mail.python.org/archives/list/python-dev@python.org/message/RFW56R7LTSC3QSNIZPNZ26FZ3ZEUCZ3C/ >> Code of Conduct: http://python.org/psf/codeofconduct/ >> > -- Marc-Andre Lemburg eGenix.com Professional Python Services directly from the Experts (#1, Jun 24 2020) >>> Python Projects, Coaching and Support ... https://www.egenix.com/ >>> Python Product Development ... https://consulting.egenix.com/ ________________________________________________________________________ ::: We implement business ideas - efficiently in both time and costs ::: eGenix.com Software, Skills and Services GmbH Pastor-Loeh-Str.48 D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg Registered at Amtsgericht Duesseldorf: HRB 46611 https://www.egenix.com/company/contact/ https://www.malemburg.com/ _______________________________________________ Python-Dev mailing list -- python-dev@python.org To unsubscribe send an email to python-dev-le...@python.org https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/HO3QAZQZXCJCLNCLU2WKQQC4O5KLKOAJ/ Code of Conduct: http://python.org/psf/codeofconduct/