[Python-ideas] Match statement brainstorm

Nick Coghlan ncoghlan at gmail.com
Thu May 19 22:37:35 EDT 2016


On 19 May 2016 at 14:15, Guido van Rossum <guido at python.org> wrote:
> 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')

For the destructuring assignment by attribute, I'd suggest the "value
as name" idiom, since it's not quite a normal assignment, as well as a
leading "." to more readily differentiate it from iterable unpacking:

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

Whether to allow ".x" as a shorthand for ".x as x" would be an open question.

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

For these, I'd guess the most flexible option would be to allow the
switch expression to be bound to a name:

    switch expr as arg:
        case arg == value: ...
        case lower_bound <= arg <= upper_bound: ...
        case arg in container: ...

Similar to with statement and for loops, this wouldn't create a new
scope, it would just bind the name in the current scope (and hence the
value would remain available after the switch statement ends)

If we went down that path, then the "assign if you can, execute this
case if you succeed" options would presumably need an explicit prefix
to indicate they're not normal expressions, perhaps something like
"?=":

    switch expr as arg:
        case ?= (.x as p, .y as q): print('x=', p, 'y=', q)
        case ?= (a, b, *_): print('a=', a, 'b=', b)
        case arg == value: ...
        case lower_bound <= arg <= upper_bound: ...
        case arg in container: ...
        else: print('Too bad')

Which would then have the further implication that it might also make
sense to support attribute unpacking as the LHS of normal assignment
statements:

    (.x as p, .y as q) = expr

In a similar vein, item unpacking might look like:

    (["x"] as p, ["y"] as q) = expr

And unpacking different structures might look like:

    switch expr:
        case ?= (.x as x, .y as y): ... # x/y as attributes
        case ?= (["x"] as x, ["y"] as y): ... # x/y as mapping
        case ?= (x, y): ... # 2-tuple (or other iterable)

Cheers,
Nick.

-- 
Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia


More information about the Python-ideas mailing list