[Python-ideas] Match statement brainstorm

Guido van Rossum guido at python.org
Thu May 19 00:15:06 EDT 2016


On Wed, May 18, 2016 at 8:17 PM, Nick Coghlan <ncoghlan at gmail.com> wrote:
> On 19 May 2016 at 08:53, Guido van Rossum <guido at python.org> wrote:
>> The one thing that Python doesn't have (and mypy doesn't add) would be
>> a match statement. The design of a Pythonic match statement would be
>> an interesting exercise; perhaps we should see how far we can get with
>> that for Python 3.7.
>
> If it's syntactic sugar for a particular variety of if/elif/else
> statement, I think that may be feasible, but you'd presumably want to
> avoid the "Can we precompute a lookup table?" quagmire that doomed PEP
> 3103's switch statement.
>
> That said, for the pre-computed lookup table case, whatever signature
> deconstruction design you came up with for a match statement might
> also be usable as the basis for a functools.multidispatch() decorator
> design.

Let's give up on the pre-computed lookup table. Neither PEP 3103 nor
PEP 275 (to which it compares itself) even gets into the unpacking
part, which would be the interesting thing from the perspective of
learning from Sum types and matching in other languages. Agreed on the
idea of trying to reuse this for multidispatch!

A few things that might be interesting to explore:

- match by value or set of values (like those PEPs)
- match by type (isinstance() checks)
- match on tuple structure, including nesting and * unpacking
(essentially, try a series of destructuring assignments until one
works)
- match on dict structure? (extension of destructuring to dicts)
- match on instance variables or attributes by name?
- match on generalized condition (predicate)?

The idea is that many of these by themselves are better off using a
classic if/elif/else structure, but a powerful matching should be
allowed to alternate between e.g. destructuring matches and value or
predicate matches. IIUC Haskell allows pattern matches as well as
conditions, which they seem to call guards or where-clauses (see
https://www.haskell.org/tutorial/patterns.html, or
http://learnyouahaskell.com/syntax-in-functions if you like your pages
more colorful). Or maybe we should be able to combine structure
matches with guards.

I guess the tuple structure matching idea is fairly easy to grasp.

The attribute idea would be similar to a duck-type check, though more
emphasizing data attributes. It would be nice if we could write a
match that said "if it has attributes x and y, assign those to local
variables p and q, and ignore other attributes". Strawman syntax could
be like this:

def demo(arg):
    switch arg:
        case (x=p, y=q): print('x=', p, 'y=', q)
        case (a, b, *_): print('a=', a, 'b=', b)
        else: print('Too bad')

Now suppose we had a Point defined like this:

Point = namedtuple('Point', 'x y z')

and some variables like this:

a = Point(x=1, y=2, z=3)
b = (1, 2, 3, 4)
c = 'hola'
d = 42

then we could call demo with these variables:

>>> demo(a)
x= 1 y= 2
>>> demo(b)
a= 1 b= 2
>>> demo(c)
a= h b= o
>>> demo(d)
Too bad
>>>

(Note the slightly unfortunate outcome for 'hola', but that's what a
destructuring assignment would do. Water under the bridge.)

Someone else can try to fit simple value equality, set membership,
isinstance, and guards into that same syntax.

-- 
--Guido van Rossum (python.org/~guido)


More information about the Python-ideas mailing list