[Python-ideas] Pattern Matching Syntax

Ed Kellett e+python-ideas at kellett.im
Thu May 3 13:18:31 EDT 2018


On 2018-05-03 15:02, Jacco van Dorp wrote:
>> # 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
> 
> I think you meant to use isinstance(y, str) ?
> This looks like an incomplete ternary as well, missing the else
> clause, so it wouldn't be a valid expression either way.
> And a NameError. y is never defined anywhere. Since there's no name
> bound to the variable being matched, would that mean a new keyword ?
> Also, in the rest you seem to be testing "x == {matchidentifier}", but
> here it suddenly looks like a boolean True would trigger a match ? And
> if so, would other boolean truthy values also trigger one, making the
> entire construct rather....limited ?
> 
> It looks like you're attempting to suggest at least 3 new language
> syntax elements here. 4 if I count the type matching of "x:int", which
> you could sell as type annotation, if those hadn't been explicitly
> optional and ignored when actually binding the names.

It's a proposal for new syntax. I suspect that you're trying to read the
left-hand side of the match cases as Python expressions. They're a
distinct thing: unbound names like 'y' are an essential component of any
non-trivial destructuring pattern match, as opposed to an error in an
expression.

I believe the intention in the example you quoted is syntax something like:

    <match-case> ::= <pattern>
                   | <pattern> "if" <expression>

where the expression is a guard expression evaluated in the context of
the matched pattern. IOW, it could be written like this, too:

number = match x:
    1 if True => "one"
    y if isinstance(y, str) => f'The string is {y}'
    _ if True => "anything"

I do see a lot of room for bikeshedding around the specific spelling.
I'm going to try to resist the temptation ;)

> And almost every other example can be solved with a dict and .get().
> The remainder uses a dict as match, and still work on if/elif
> perfectly fine.

How about this?

def hyperop(n, a, b):
    return match (n, a, b):
        (0, _, b) => b + 1
        (1, a, 0) => a
        (2, _, 0) => 0
        (_, _, 0) => 1
        (n, a, b) => hyperop(n-1, a, hyperop(n, a, b-1))

versus:

def hyperop(n, a, b):
    if n == 0:
        return b + 1
    if n == 1 and b == 0:
        return a
    if n == 2 and b == 0:
        return 0
    if b == 0:
        return 1
    return hyperop(n-1, a, hyperop(n, a, b-1))

Of course the latter *works* (sort of: implementing tetration by
recursively adding ones never really works) but it's excessively
verbose, it's easy to make mistakes when writing it out, and at least in
my opinion it's harder to see what it does.

It also raises some small but annoying questions, like "do I use if or
elif?", "do I use an if for the last case too?", "do I nest the b == 0
cases?", and, if we had used an if for the last case, what we do if we
get to the end anyway.

> Also, I'd say "but other people do it" isn't a valid reason for
> implementation. There's plenty people doing stupid things, that
> doesn't mean it's a good idea to do it to. If they idea can't stand on
> it's own, it's not worth it.
> 
> From the syntax corner, it also doesn't really look like Python to me.

I agree, but I'm sure someone can come up with something prettier.

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: OpenPGP digital signature
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20180503/0a6a73a6/attachment.sig>


More information about the Python-ideas mailing list