[Python-ideas] Pattern Matching Syntax
Chris Angelico
rosuav at gmail.com
Thu May 3 14:01:55 EDT 2018
On Fri, May 4, 2018 at 3:18 AM, Ed Kellett <e+python-ideas at kellett.im> wrote:
> 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 ;)
Okay, let me try to tease apart your example.
1) A literal matches anything that compares equal to that value.
2) A name matches anything at all, and binds it to that name.
2a) An underscore matches anything at all. It's just a name, and
follows a common convention.
3) "if cond" modifies the prior match; if the condition evaluates as
falsey, the match does not match.
4) As evidenced below, a comma-separated list of comparisons matches a
tuple with as many elements, and each element must match.
Ultimately, this has to be a series of conditions, so this is
effectively a syntax for an elif tree as an expression.
For another example, here's a way to use inequalities to pick a
numeric formatting:
display = match number:
x if x < 1e3: f"{number}"
x if x < 1e6: f"{number/1e3} thousand"
x if x < 1e9: f"** {number/1e6} million **"
x if x < 1e12: f"an incredible {number/1e9} billion"
_: "way WAY too many"
I guarantee you that people are going to ask for this to be spelled
simply "< 1e3" instead of having the "x if x" part. :)
> 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))
I have no idea what this is actually doing, and it looks like a port
of Haskell code. I'd want to rewrite it as a 'while' loop with maybe
one level of recursion in it, instead of two. (Zero would be better,
but I think that's not possible. Maybe?) Is this something that you do
a lot of? Is the tuple (n, a, b) meaningful as a whole, or are the
three values independently of interest?
Not sure how this is useful without a lot more context.
ChrisA
More information about the Python-ideas
mailing list