[Python-ideas] Fwd: Pattern Matching Syntax

David Mertz mertz at gnosis.cx
Thu May 3 16:13:40 EDT 2018


That's buggy code in either version. A month is not necessarily 30 days,
and a year is not necessarily 365 days. An example without such painful
bugs might be more compelling... It also likely makes the use case less
obvious for the bug-free version.

On Thu, May 3, 2018, 2:37 PM Robert Roskam <raiderrobert at gmail.com> wrote:

> Hey Chris,
>
> So I started extremely generally with my syntax, but it seems like I
> should provide a lot more examples of real use. Examples are hard. Here's
> my hastily put together example from an existing piece of production code:
>
>
> # Existing Production Code
> from datetime import timedelta, date
> from django.utils import timezone
>
>
> def convert_time_to_timedelta(unit:str, amount:int, now:date):
>     if unit in ['days', 'hours', 'weeks']:
>         return timedelta(**{unit: amount})
>     elif unit == 'months':
>         return timedelta(days=30 * amount)
>     elif unit == 'years':
>         return timedelta(days=365 * amount)
>     elif unit == 'cal_years':
>         return now - now.replace(year=now.year - amount)
>
>
>
>
> # New Syntax for same problem
>
>
> def convert_time_to_timedelta_with_match(unit:str, amount:int, now:date):
>  return match unit:
>      '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)
>
>
>
>
>
>
>
> On Thursday, May 3, 2018 at 2:02:54 PM UTC-4, Chris Angelico wrote:
>>
>> On Fri, May 4, 2018 at 3:18 AM, Ed Kellett <e+pytho... 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
>> _______________________________________________
>> Python-ideas mailing list
>> Python... at python.org
>> https://mail.python.org/mailman/listinfo/python-ideas
>> Code of Conduct: http://python.org/psf/codeofconduct/
>>
> _______________________________________________
> Python-ideas mailing list
> Python-ideas at python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20180503/0e06f239/attachment-0001.html>


More information about the Python-ideas mailing list