[Python-ideas] Pattern Matching Syntax

Chris Angelico rosuav at gmail.com
Thu May 3 15:17:37 EDT 2018


On Fri, May 4, 2018 at 5:02 AM, Robert Roskam <raiderrobert at gmail.com> wrote:
> Hey Chris,
>
> Thanks for bringing that up! Before submitting this, I actually had the
> syntax for multiple matches for one arm being separated by or. And frankly I
> just didn't like how that looked for more than 3 items:
>
> '1' or '2' or '3' or '4' or '5' vs  '1', '2', '3', '4', '5'
>
> But you're right. The syntax should be for tuples instead.

Agreed.

> Here's my revised syntax, using a guard instead for the moment:
>
> def convert_time_to_timedelta_with_match(unit:str, amount:int, now:date):
>  return match unit:
>      x if x in ('days', 'hours', 'weeks') => timedelta(**{unit: amount})
>      'months' => timedelta(days=30 * amount)
>      'years' => timedelta(days=365 * amount)
>      'cal_years' => now - now.replace(year=now.year - amount)

And then this comes down to the same as all the other comparisons -
the "x if x" gets duplicated. So maybe it would be best to describe
this thus:

match <expr> :
    <expr> | (<comp_op> <expr>) => <expr>

If it's just an expression, it's equivalent to a comp_op of '=='. The
result of evaluating the match expression is then used as the left
operand for ALL the comparisons. So you could write your example as:

return match unit:
    in ('days', 'hours', 'weeks') => timedelta(**{unit: amount})
    'months' => timedelta(days=30 * amount)
    'years' => timedelta(days=365 * amount)
    'cal_years' => now - now.replace(year=now.year - amount)

Then there's room to expand that to a comma-separated list of values,
which would pattern-match a tuple.

ChrisA


More information about the Python-ideas mailing list