<div dir="ltr"><font face="monospace, monospace">On Tue, May 24, 2016 at 6:43 AM, Guido van Rossum <<a href="mailto:guido@python.org">guido@python.org</a>> wrote:<br>> On Mon, May 23, 2016 at 7:57 PM, Michael Selik <<a href="mailto:michael.selik@gmail.com">michael.selik@gmail.com</a>> wrote:<br>>> Ok, let me refocus on the idea of assign-if-you-can during matching, not<br>>> just sugar for try/except.<br>>><br>>> The matching features of equality, inequality, predicates, and subtype are<br>>> already available via if/elif. The matching features of destructuring,<br>>> assignment, and post-assignment guards need new syntax. The other proposals<br>>> in this thread suggest a new keyword or keyword pair like switch/case.<br>>> Instead, why not extend if/elif with a new operator?<br>>><br>>> def demo(arg):<br>>>     if p, q ?= arg.x, arg.y:                        # dict structure<br>>>     elif x ?= arg.x and isinstance(x, int)          # assignment + guard<br>>>     elif a, b, *_ ?= arg:                           # tuple structure<br>>>     elif isinstance(arg, Mapping):                  # nothing new here<br>>><br>>><br>[...]<br>> This idea has some clear advantages -- it's unambiguous about the<br>> order of matching, and combines clearly with existing conditions. It<br>> also seems like it would support "recursive" matching nicely, by<br>> allowing you to chain additional unpacking operators. ("Recursive"<br>> because IIUC that's what Haskell calls matches inside matches --<br>> similar to nested tuple unpackings like (a, (b, c)) = in Python.)<br>><br>> The trick is to find a good syntax for the conditional assignment;<br>> using ? has been rejected by this group in the past for other<br>> conditionalisms.<br><br>Yeah, and indeed it's not obvious how to draw the line between whether the conditional assignment should return a truth value or raise an exception, as I think Greg was already implying. For instance, what would `a ?= data[0]` do, if data[0] raises, say, a TypeError. Should it be caught or be raised? Anyway, maybe it is possible to draw that line in a reasonable way.<br><br>So here's a<div class="gmail_default" style="font-family:monospace,monospace;display:inline">​nother syntax</div>:<br><br>Introduce a <div class="gmail_default" style="font-family:monospace,monospace;display:inline">​new ​</div>keyword `given`, which <div class="gmail_default" style="font-family:monospace,monospace;display:inline">​could be used as</div> a prefix operator with roughly the following properties<br><br>given a    <div class="gmail_default" style="font-family:monospace,monospace;display:inline">​   ​       </div># True if the name a is bound to something<br>given b.c     <div class="gmail_default" style="font-family:monospace,monospace;display:inline">​ ​      </div># roughly equivalent to hasattr(b, 'c')<br>given a, b.c   <div class="gmail_default" style="font-family:monospace,monospace;display:inline">​      ​</div># same as (given a and given b.c)</font><div><font face="monospace, monospace">given d, e = a, b.c <div class="gmail_default" style="font-family:monospace,monospace;display:inline">​ ​</div># like `given a, b.c` but with added assignment<br><br>Then one could do (<div class="gmail_default" style="font-family:monospace,monospace;display:inline">​expanding on</div> the above demo example)<br><br></font><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><font face="monospace, monospace">def demo(arg):<br></font><font face="monospace, monospace">    if given p, q = arg.x, arg.y:<br></font><font face="monospace, monospace">        # do somet</font><span style="font-family:monospace,monospace">h</span><span style="font-family:monospace,monospace">ing</span></blockquote><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><font face="monospace, monospace">    elif given x = arg.x and isinstance(x, int):<br></font><font face="monospace, monospace">        # do somet</font><span style="font-family:monospace,monospace">​</span><span style="font-family:monospace,monospace">​hing</span></blockquote><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><font face="monospace, monospace">    elif given a, b, *_ = arg:<br></font><font face="monospace, monospace">        # do somet</font><span style="font-family:monospace,monospace">​h​</span><span style="font-family:monospace,monospace">ing</span></blockquote><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><font face="monospace, monospace">    elif isinstance(arg, Mapping):<br></font><font face="monospace, monospace">        # do something</font></blockquote><font face="monospace, monospace"><br><div class="gmail_default" style="font-family:monospace,monospace;display:inline">​# Or something like this:</div></font><div><span style="font-family:monospace,monospace">​<div class="gmail_default" style="font-family:monospace,monospace;display:inline">​</div></span></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><span style="font-family:monospace,monospace"><div class="gmail_default" style="font-family:monospace,monospace;display:inline">def demo2(arg):​</div></span></div><div><font face="monospace, monospace"><div class="gmail_default" style="font-family:monospace,monospace;display:inline">​    global importan​t_value</div></font></div><div><div><font face="monospace, monospace"><div class="gmail_default" style="font-family:monospace,monospace;display:inline">​</div></font><span style="font-family:monospace,monospace">​<div class="gmail_default" style="font-family:monospace,monospace;display:inline">​    if not given important_value:</div></span></div></div><div><div><span style="font-family:monospace,monospace"><div class="gmail_default" style="font-family:monospace,monospace;display:inline">        important_value = compute_important_value()</div></span></div></div></blockquote><div><div><font face="monospace, monospace"><br></font></div><div><span style="font-family:monospace,monospace">​-- Koos​</span><br></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace"><div class="gmail_default" style="font-family:monospace,monospace;display:inline">​PS. I like seeing the word "brainstorm" used here. I'm not sure if I've seen that here before. I think that means that we try to see the good parts of the presented ideas and send further ideas and thoughts to see if we can find something useful -- even if the presented ideas are not yet optimal. (Of course that does not mean that the ideas should not be presented clearly!) Anyway, in the end, if nothing is found, it is easy to just drop the whole concept.</div></font></div><div><font face="monospace, monospace"><div class="gmail_default" style="font-family:monospace,monospace;display:inline">​</div><br>> --<br>> --Guido van Rossum (<a href="http://python.org/~guido">python.org/~guido</a>)<br>> _______________________________________________<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">https://mail.python.org/mailman/listinfo/python-ideas</a><br>> Code of Conduct: <a href="http://python.org/psf/codeofconduct/">http://python.org/psf/codeofconduct/</a></font></div></div></div></div>