<div dir="ltr"><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial">Note that most languages that you mentioned as references are functional (so they don't have a statement/expression distinction like Python has), and those that are not, have matching statements. The only exception is Javascript, but in Javascript the distinction is not that</div><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial">hard given that it has the idiom (function() {stmt; stmt; stmt})() to have any statement block as an expression. And again, as I mentioned it's an outlier. Other imperative languages like C, Java, have of course switch statements which are similar</div><br class="m_-569127626409945784gmail-Apple-interchange-newline">Making a quick search for real code that could benefit for this, I mostly found situations where a matching *statement* would be required instead of a matching *expression*. To give you the examples I found in the stdlib for Python3.6 (I grepped for "elif" and looked for "similar" branches manually, covering the first ~20%):<div><br></div><div>fnmatch.translate (match c: ... string options)</div><div><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initial">telnetlib.Telnet.process_rawq (match len(self.iacseq): ... integer options)</div><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initial">mimetypes[module __main__ body] (match opt: ... multiple str options per match)</div><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initial">typing._remove_dups_flatten (match p: ... isinstance checks + custom condition) [this *could* be an expression with some creativity]</div><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initial">typing.GenericMeta.__getitem__ (match self: ... single and multiple type options by identity)</div>turtle.Shape.__init__ (match type_:... str options)</div><div>turtle.TurtleScreen._color (match len(cstr): ... int options) </div><div><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initial">turtle.TurtleScreen.colormode (match cmode: ... mixed type options) </div></div><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initial">turtle.TNavigator.distance (match x: ... isinstance checks) [could be an expression]</div><div><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initial">turtle.TNavigator.towards (match x: ... isinstance checks) [could be an expression]</div>turtle.TPen.color (match l: ... integer options. l is set to len(args) the line before)</div><div>turtle._TurtleImage._setshape (match self._type: ... str options) [could be an expression]</div><div><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initial">turtle.RawTurtle.__init__ (match canvas: ... isinstance checks)</div>turtle.RawTurtle.clone (match ttype: ... str options) [ could be an expression]</div><div><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial">turtle.RawTurtle._getshapepoly (match self._resizemode: ... str options, one with a custom condition or'ed)</div><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initial"><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial">turtle.RawTurtle._drawturtle (match ttype: ... str options)</div><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial"><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initial;background-color:rgb(255,255,255)">turtle.RawTurtle.stamp (match ttype: ... str options)</div><span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">turtle.RawTurtle._undo (match action: ... str options)</span><br class="m_-569127626409945784gmail-Apple-interchange-newline">ntpath.expandvars (match c: ... str optoins)</div><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial">sre_parse.Subpattern.getwidth (match op: ... nonliteral int constants, actually a NamedIntConstant which subclasses int)</div><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial">sre_parse._class_escape (match c: ... string options with custom conditions, and inclusion+equality mixed)</div><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial"><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initial;background-color:rgb(255,255,255)">sre_parse._escape (match c: ... string options with custom conditions, and inclusion+equality mixed)</div>sre_parse._parse ( match this: ... string options with in, not in, and equality)</div><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial"><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initial;background-color:rgb(255,255,255)">sre_parse._parse ( match char: ... string options with in, and equality)</div>sre_parse.parse_template (match c: ... string options with in)<br class="m_-569127626409945784gmail-Apple-interchange-newline">netrc.netrc._parse (match tt: ... string options with custom conditions)<br class="m_-569127626409945784gmail-Apple-interchange-newline"><span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">netrc.netrc._parse (match tt: ... string options with custom conditions) [not a duplicate, there are two possible statements here]</span></div><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial">argparse.HelpFormatter._<wbr>format_args (match action.nargs: ... str/None options) <span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">[this *could* be an expression with some creativity/transformations]</span></div><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial"><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initial;background-color:rgb(255,255,255)">argparse.ArgumentParser._get_<wbr>nargs_pattern (match nargs: ... str/None options) <span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">[could be an expression]</span></div><span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">argparse.ArgumentParser._get_<wbr>values (match action.nargs: ... str/None options with extra conditions)</span><br class="m_-569127626409945784gmail-Apple-interchange-newline">_strptime._strptime (match group_key: ... str options)</div><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial">datetime._wrap_strftime (match ch: ... str optoins)</div><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial">pickletools.optimize (match opcode,name: ... str options with reverse inclusion and equiality)<br class="m_-569127626409945784gmail-Apple-interchange-newline">json/encoder._make_iterencode(match value: ... mixed options and isinstance checks)</div><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial"><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initial;background-color:rgb(255,255,255)"><span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">json/encoder._make_iterencode._iterencode dict (match key: ... mixed options and isinstance checks)</span><br class="gmail-Apple-interchange-newline">json/encoder._make_iterencode._iterencode dict (match value: ... mixed options and isinstance checks)</div><span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">json/encoder._make_iterencode._iterencode (match o: ... mixed options and isinstance checks)</span><br class="gmail-Apple-interchange-newline">json/scanner.py_make_scanner._scan_once (match nextchar: ... str options) [could be turned into expression with some transformation]</div><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial">unittest.mock._Call.__new__ (match _len: ... int options)</div><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial"><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initial;background-color:rgb(255,255,255)">unittest.mock._Call.eq__ (match len_other: ... int options)</div><br class="gmail-Apple-interchange-newline">(I'm not saying that all these should be match statements, only that they could be). Cases where an expression would solve the issue are somewhat uncommon (there are many state machines, including many string or argument parsers that set state depending on the option, or object builders that grow data structures). An usual situation is that some of the branches need to raise exceptions (and raise in python is a statement, not an expression). This could be workarounded making the default a raise ValueError that can be caught and reraised as soemthing else, but that would end up making the code deeper, and IMO, more complicated. Also, many of the situations where an expression could be used, are string matches where a dictionary lookup would work well anyway.<br></div></div></div><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initial"><br></div><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initial">My conclusions for this are:</div><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initial">1. It makes more sense to talk about a statement, not an expression</div><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initial">2. good/clear support for strings, ints and isinstancechecks is essential (other fancier things may help more circumstancially)</div><div><div>3. the "behaviour when there's no match" should be quite flexible. I saw many "do nothing" and many "do something" (with a large part of the latter being "raise an exception")</div><div>4. There's a pattern of re-evaluating something on each branch of an if/elif (like len(foo) or self.attr); and also common to create a dummy variable just before the if/elif. This can also be fodder for PEP-572 discussion</div><div><br></div></div><div>That's what I have for now</div></div><div class="gmail_extra"><br><div class="gmail_quote">On 4 May 2018 at 08:26, Jacco van Dorp <span dir="ltr"><<a href="mailto:j.van.dorp@deonet.nl" target="_blank">j.van.dorp@deonet.nl</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Would this be valid?<br>
<span class=""><br>
# Pattern matching with guards<br>
x = 'three'<br>
<br>
</span>number = match x:<br>
1 => "one"<br>
y if y is str => f'The string is {y}'<br>
z if z is int => f'the int is {z}'<br>
<span class=""> _ => "anything"<br>
<br>
print(number) # The string is three<br>
<br>
</span>If so, why are y and z both valid here ? Is the match variable rebound<br>
to any other ? Or even to all names ?<br>
<br>
ofc, you could improve the clarity here with:<br>
<br>
number = match x as y:<br>
<br>
or any variant thereof. This way, you'd explicitely bind the variable<br>
you use for testing. If you don't, the interpreter would never know<br>
which ones to treat as rebindings and which to draw from surrounding<br>
scopes, if any.<br>
<br>
I also haven't really seen a function where this would be better than<br>
existing syntax, and the above is the only one to actually try<br>
something not possible with dicts. The type checking one could better<br>
be:<br>
<br>
x = 1<br>
d = {<br>
int:"integer",<br>
float:"float",<br>
str:"str"<br>
}<br>
d.get(type(x), None)<br>
<br>
The production datetime code could be:<br>
<span class=""><br>
def convert_time_to_timedelta_<wbr>with_match(unit:str, amount:int, now:date):<br>
</span> return {<br>
"days":timedelta(**{unit: amount}),<br>
"hours":timedelta(**{unit: amount}),<br>
"weeks":timedelta(**{unit: amount}),<br>
# why not something like subtracting two dates here to get an<br>
accurate timedelta for your specific interval ?<br>
"months":timedelta(days = 30*amount), # days = (365.25 /<br>
12)*amount ? Would be a lot more accurate for average month length.<br>
(30.4375)<br>
"years":timedelta(days=365*<wbr>amount), # days = 365.25*amount ?<br>
"cal_years":timedelta(now - now.replace(year=now.year - amount)),<br>
}.get(unit)<br>
<br>
I honestly don't see the advantages of new syntax here.<br>
Unless you hate the eager evaluation in the dict literal getting<br>
indexed, so if it's performance critical an if/else might be better.<br>
But I can't see a match statement outperforming if/else. (and if you<br>
really need faster than if/else, you should perhaps move that bit of<br>
code to C or something.)<br>
<div class="HOEnZb"><div class="h5"><br>
2018-05-04 0:34 GMT+02:00 Ed Kellett <<a href="mailto:e%2Bpython-ideas@kellett.im">e+python-ideas@kellett.im</a>>:<br>
> On 2018-05-03 20:17, Chris Angelico wrote:<br>
>>> def convert_time_to_timedelta_<wbr>with_match(unit:str, amount:int, now:date):<br>
>>> return match unit:<br>
>>> x if x in ('days', 'hours', 'weeks') => timedelta(**{unit: amount})<br>
>>> 'months' => timedelta(days=30 * amount)<br>
>>> 'years' => timedelta(days=365 * amount)<br>
>>> 'cal_years' => now - now.replace(year=now.year - amount)<br>
>><br>
>> And then this comes down to the same as all the other comparisons -<br>
>> the "x if x" gets duplicated. So maybe it would be best to describe<br>
>> this thus:<br>
>><br>
>> match <expr> :<br>
>> <expr> | (<comp_op> <expr>) => <expr><br>
>><br>
>> If it's just an expression, it's equivalent to a comp_op of '=='. The<br>
>> result of evaluating the match expression is then used as the left<br>
>> operand for ALL the comparisons. So you could write your example as:<br>
>><br>
>> return match unit:<br>
>> in ('days', 'hours', 'weeks') => timedelta(**{unit: amount})<br>
>> 'months' => timedelta(days=30 * amount)<br>
>> 'years' => timedelta(days=365 * amount)<br>
>> 'cal_years' => now - now.replace(year=now.year - amount)<br>
>><br>
>> Then there's room to expand that to a comma-separated list of values,<br>
>> which would pattern-match a tuple.<br>
><br>
> I believe there are some problems with this approach. That case uses no<br>
> destructuring at all, so the syntax that supports destructuring looks<br>
> clumsy. In general, if you want to support something like:<br>
><br>
> match spec:<br>
> (None, const) => const<br>
> (env, fmt) if env => fmt.format(**env)<br>
><br>
> then I think something like the 'if' syntax is essential for guards.<br>
><br>
> One could also imagine cases where it'd be useful to guard on more<br>
> involved properties of things:<br>
><br>
> match number_ish:<br>
> x:str if x.lower().startswith('0x') => int(x[2:], 16)<br>
> x:str => int(x)<br>
> x => x #yolo<br>
><br>
> (I know base=0 exists, but let's imagine we're implementing base=0, or<br>
> something).<br>
><br>
> I'm usually against naming things, and deeply resent having to name the<br>
> x in [x for x in ... if ...] and similar constructs. But in this<br>
> specific case, where destructuring is kind of the point, I don't think<br>
> there's much value in compromising that to avoid a name.<br>
><br>
> I'd suggest something like this instead:<br>
><br>
> return match unit:<br>
> _ in {'days', 'hours', 'weeks'} => timedelta(**{unit: amount})<br>
> ...<br>
><br>
> So a match entry would be one of:<br>
> - A pattern. See below<br>
> - A pattern followed by "if" <expr>, e.g.:<br>
> (False, x) if len(x) >= 7<br>
> - A comparison where the left-hand side is a pattern, e.g.:<br>
> _ in {'days', 'hours', 'weeks'}<br>
><br>
> Where a pattern is one of:<br>
> - A display of patterns, e.g.:<br>
> {'key': v, 'ignore': _}<br>
> I think *x and **x should be allowed here.<br>
> - A comma-separated list of patterns, making a tuple<br>
> - A pattern enclosed in parentheses<br>
> - A literal (that is not a formatted string literal, for sanity)<br>
> - A name<br>
> - A name with a type annotation<br>
><br>
> To give a not-at-all-motivating but hopefully illustrative example:<br>
><br>
> return match x:<br>
> (0, _) => None<br>
> (n, x) if n < 32 => ', '.join([x] * n)<br>
> x:str if len(x) <= 5 => x<br>
> x:str => x[:2] + '...'<br>
> n:Integral < 32 => '!' * n<br>
><br>
> Where:<br>
> (0, 'blorp') would match the first case, yielding None<br>
> (3, 'hello') would match the second case, yielding<br>
> "hello, hello, hello"<br>
> 'frogs' would match the third case, yielding "frogs"<br>
> 'frogs!' would match the fourth case, yielding "fr..."<br>
> 3 would match the fifth case, yielding '!!!'<br>
><br>
> I think the matching process would mostly be intuitive, but one detail<br>
> that might raise some questions: (x, x) could be allowed, and it'd make<br>
> a lot of sense for that to match only (1, 1), (2, 2), ('hi', 'hi'), etc.<br>
> But that'd make the _ convention less useful unless it became more than<br>
> a convention.<br>
><br>
> All in all, I like this idea, but I think it might be a bit too heavy to<br>
> get into Python. It has the feel of requiring quite a lot of new things.<br>
><br>
><br>
</div></div><div class="HOEnZb"><div class="h5">> ______________________________<wbr>_________________<br>
> Python-ideas mailing list<br>
> <a href="mailto:Python-ideas@python.org">Python-ideas@python.org</a><br>
> <a href="https://mail.python.org/mailman/listinfo/python-ideas" rel="noreferrer" target="_blank">https://mail.python.org/<wbr>mailman/listinfo/python-ideas</a><br>
> Code of Conduct: <a href="http://python.org/psf/codeofconduct/" rel="noreferrer" target="_blank">http://python.org/psf/<wbr>codeofconduct/</a><br>
><br>
______________________________<wbr>_________________<br>
Python-ideas mailing list<br>
<a href="mailto:Python-ideas@python.org">Python-ideas@python.org</a><br>
<a href="https://mail.python.org/mailman/listinfo/python-ideas" rel="noreferrer" target="_blank">https://mail.python.org/<wbr>mailman/listinfo/python-ideas</a><br>
Code of Conduct: <a href="http://python.org/psf/codeofconduct/" rel="noreferrer" target="_blank">http://python.org/psf/<wbr>codeofconduct/</a><br>
</div></div></blockquote></div><br><br clear="all"><div><br></div>-- <br><div class="gmail_signature" data-smartmail="gmail_signature"><div dir="ltr"><div><div dir="ltr"><div dir="ltr">Daniel F. Moisset - <span style="font-size:small">UK Country Manager - Machinalis Limited</span><div><a href="http://www.machinalis.com" target="_blank">www.machinalis.co.uk</a></div><div>Skype: @dmoisset T: <span style="background-color:transparent;font-family:Arial;font-size:8pt;white-space:pre-wrap">+ 44 7398 827139</span></div><div><span><p dir="ltr" style="line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:8pt;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap">1 Fore St, London, EC2Y 9DT</span></p><p dir="ltr" style="line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="background-color:transparent;font-family:Arial;font-size:8pt;white-space:pre-wrap">Machinalis Limited is a company registered in England and Wales. Registered number: 10574987.</span></p></span></div></div></div></div></div></div>
</div>