[Python-ideas] Pattern Matching Syntax (reprise)

Patrick Vergain pvergain at gmail.com
Wed Sep 19 02:01:49 EDT 2018


Le mar. 18 sept. 2018 à 13:39, Tobias Kohn <kohnt at tobiaskohn.ch> a écrit :

> Hello Everyone,
>
> Please excuse my being late for properly responding to the last thread on
> "Pattern Matching Syntax" [1].  As Robert Roskam has already pointed out at
> the beginning of that thread, there has been much previous discussion about
> adding pattern matching to Python, and several proposals exist.  It is
> therefore not my intention to propose yet another syntax choice for pattern
> matching, but more to share my experience with implementing it, in the hope
> of making a worthwhile contribution to the overall discussion.
>
> This summer, I basically ended up requiring pattern matching in Python for
> a research project I am working on.  Some initial hacks have then grown
> into a library for pattern matching in Python [2].  On the one hand, my
> design is certainly heavily influence by Scala, with which I also work on a
> regular basis.  On the other hand, I ran into various difficulties,
> challanges, and it has been particularly important to me to find a design
> that blends well with Python, and harnesses what Python already offers.
>
> I have written down my experience in the form of a discussion on several
> options concerning syntax [3], and implementation [4], respectively.  As
> the articles have turned out longer than I originally intended, it might
> take up too much time for those who have little interest in this matter in
> the first place.  However, considering that the subject of pattern matching
> has been coming up rather regularly, my experience might help to contribute
> something to the discussion.  Let me provide a brief summary here:
>
> *1. Pattern Matching is not Switch/Case*
> --------------------------------------
> When I am talking about pattern matching, my goal is to do a deep
> structural comparison, and extract information from an object.  Consider,
> for instance, the problem of optimising the AST of a Python program, and
> eliminate patterns of the form `x + 0`, and `x - 0`.  What pattern matching
> should be offering here is a kind of comparison along the lines of:
> `if node == BinOp(?, (Add() or Sub()), Num(0)): ...`
> Ideally, it should also return the value of what is marked by the question
> mark `?` here, and assign it to a variable `left`, say.  The above
> comparison is often written as something like, e. g.:
> `case BinOp(left, Add()|Sub(), Num(0)): ...`
> This use of `case`, however, is not the same as a switch-statement.
>
> *2. Orthogonality*
> ----------------
> Getting the syntax and semantics of nested blocks right is hard.  Every
> block/suite in Python allows any kind of statements to occur, which allows
> for things like nested functions definitions, or having more than just
> methods in a class.  If we use a two-levelled block-structure, we run into
> the problem of finding good semantics for what the following means (note
> the variable `x` here):
> ```
> match node:
>     x = 0
>     case BinOp(left, Add(), Num(0)):
>         ...
>     x += 1
>     case BinOp(left, Mul(), Num(1)):
>         ...
> ```
> In the case of a "switch block", such additional statements like the
> `x=0`, and `x+=1` can become quite problematic.  On the other hand,
> requiring all statements inside the block to be case-statements violates
> the orthogonality found otherwise in Python.
>
> I feel that this dilemma is one of the core issues why the syntax of
> switch statements, or pattern matching seems so exceptionally hard.  In the
> end, it might therefore, indeed, make more sense to find a structure that
> is more in line with if/elif/else-chains.  This would lead to a form of
> pattern matching with little support for switch-statement, though.
>
> *3. Implementation*
> -----------------
> For the implementation of pattern matching, my package compiles the
> patterns into context-manager-classes, adds these classes in the background
> to the code, and then uses `with`-statements to express the
> `case`-statement.  If have found a neat way to make the execution of a
> `with`-statement's body conditional.
>
> Two things have been curcially important in the overall design: first, the
> "recompilation" cannot change the structure of the original code, or add
> any line.  This way, all error messages, and tooling should work as
> expected; the invasive procedure should be as minimal as possible.  Second,
> it is paramount that the semantics of how Python works is being preserved.
> Even though the actual matching of patterns is done in external classes,
> all names must be resolved "locally" where the original `case`-statement
> lives.  Similarly, the variables defined by the pattern are to local
> variables, which are assigned if, and only if, the pattern actually matches.
>
> Should pattern matching ever be added to Python properly, then there will
> be no need to use `with`-statements and context managers, of course.  But
> the implementation must make sure, nonetheless, that the usual semantics
> with name resolving of Python is being respected.
>
> *4. Syntax of Patterns*
> ---------------------
> The syntax of patterns themselves has been guided by two principles
> (again).  First, if there is a way to already express the same thing in
> Python, use that.  This applies, in particular, to sequence unpacking.
> Second, patterns specify a possible way how the object in question could
> have been created, or constructed in the first place.  Hence, it is no
> accident that the pattern `BinOp(left, Add(), Num(0))` above looks almost
> like a constructor.
>
> Other implementation are happy to redefine the meanings of operators like
> `in`, or `is` (as in, e. g., `case x is str:`).  While this might look very
> convenient at first, it will most probably lead to many subsequent bugs
> where people write `if x is str:` to mean the same thing (namely test the
> type of `x`).  Even though expressing patterns requires reusing some
> operators in a new way, we have to extremely careful to choose widely, and
> minimise confusion, and surprises.
>
>
> Pattern matching could certainly make a great addition to Python, and
> various current implementations act as proof of concepts.  However,
> choosing an appropriate syntax for pattern matching is hard, and we should
> work hard to make sure that any such addition feels natural in Python, even
> at the expense of having to write more, and being not as terse as other
> languages.
>
> I hope my thoughts in this matter can make a worthwhile constribution to
> the discussion.  And I would like to emphasise once more, that my goal is
> not to propose a new syntax for pattern matching, but to report on my
> experience while implementing it.
>
> Kind regards,
> Tobias Kohn
>
>
> [1] https://groups.google.com/d/topic/python-ideas/nqW2_-kKrNg/discussion
> [2] https://github.com/Tobias-Kohn/pyPMatch
> [3]
> https://tobiaskohn.ch/index.php/2018/09/18/pattern-matching-syntax-in-python/
> [4]
> https://tobiaskohn.ch/index.php/2018/09/12/implementing-pattern-matching/
> _______________________________________________
> 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/
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20180919/33c25e49/attachment-0001.html>


More information about the Python-ideas mailing list