<div dir="ltr">Hey Steven,<div><br></div><div>I'm also at PyCon. Shall we take this off list and attempt to meet up and discuss?<br><br>On Friday, May 11, 2018 at 12:36:32 PM UTC-4, ste...@rigetti.com wrote:<blockquote class="gmail_quote" style="margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir="ltr">Hi everyone, I’m also a first time poster to python-ideas so I apologize if reviving a week old thread is bad form. I emailed Guido out of the blue to share some thoughts on the JavaScript pattern matching proposal’s applicability to Python and he encouraged me to post those thoughts here.<br><br>The best argument for pattern matching is to support what Daniel F Mossat above calls “structural patterns”. These go beyond simple value matching or boolean conditions that are better served with other constructs like if statements. Structural pattern matching allows for reasoning about the shape of data.<br><br>As a practical example, in my day job I work as a software engineer at a startup that builds quantum computers. Python has been a great language for writing physics experiments and doing numerical simulations. However, our codebase contains a lot of `isinstance` calls due to the need to write converters from the physics experiment definition language to quantum assembly instructions. There’s some examples in our open source code as well, for instance here: <a href="https://github.com/rigetticomputing/pyquil/blob/master/pyquil/quil.py#L641" rel="nofollow" target="_blank" onmousedown="this.href='https://www.google.com/url?q\x3dhttps%3A%2F%2Fgithub.com%2Frigetticomputing%2Fpyquil%2Fblob%2Fmaster%2Fpyquil%2Fquil.py%23L641\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFUCe9cNL29zWLlLqV2XeNWFOf5iw';return true;" onclick="this.href='https://www.google.com/url?q\x3dhttps%3A%2F%2Fgithub.com%2Frigetticomputing%2Fpyquil%2Fblob%2Fmaster%2Fpyquil%2Fquil.py%23L641\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFUCe9cNL29zWLlLqV2XeNWFOf5iw';return true;">https://github.com/<wbr>rigetticomputing/pyquil/blob/<wbr>master/pyquil/quil.py#L641</a> . This could be written more succinctly as:<br><br><div style="background-color:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid;border-width:1px"><code><div><span style="color:#000">match instr</span><span style="color:#660">:</span><span style="color:#000"><br>    </span><span style="color:#008">case</span><span style="color:#000"> </span><span style="color:#606">Gate</span><span style="color:#660">(</span><span style="color:#000">name</span><span style="color:#660">,</span><span style="color:#000"> </span><span style="color:#008">params</span><span style="color:#660">,</span><span style="color:#000"> qubits</span><span style="color:#660">):</span><span style="color:#000"> result</span><span style="color:#660">.</span><span style="color:#000">append</span><span style="color:#660">(</span><span style="color:#606">Gate</span><span style="color:#660">(</span><span style="color:#000">name</span><span style="color:#660">,</span><span style="color:#000"> </span><span style="color:#008">params</span><span style="color:#660">,</span><span style="color:#000"> </span><span style="color:#660">[</span><span style="color:#000">qubit_mapping</span><span style="color:#660">[</span><span style="color:#000">q</span><span style="color:#660">]</span><span style="color:#000"> </span><span style="color:#008">for</span><span style="color:#000"> q </span><span style="color:#008">in</span><span style="color:#000"> qubits</span><span style="color:#660">])</span><span style="color:#000"><br>    </span><span style="color:#008">case</span><span style="color:#000"> </span><span style="color:#606">Measurement</span><span style="color:#660">(</span><span style="color:#000">qubit</span><span style="color:#660">,</span><span style="color:#000"> classical_reg</span><span style="color:#660">):</span><span style="color:#000"> result</span><span style="color:#660">.</span><span style="color:#000">append</span><span style="color:#660">(</span><span style="color:#606">Measurement</span><span style="color:#660">(</span><span style="color:#000">qubi<wbr>t_mapping</span><span style="color:#660">[</span><span style="color:#000">qubit</span><span style="color:#660">],</span><span style="color:#000"> classical_reg</span><span style="color:#660">)</span><span style="color:#000"><br>    </span><span style="color:#008">else</span><span style="color:#660">:</span><span style="color:#000"> result</span><span style="color:#660">.</span><span style="color:#000">append</span><span style="color:#660">(</span><span style="color:#000">instr</span><span style="color:#660">)</span></div></code></div><br>Something that I also haven’t seen discussed yet is how well this would work with the new Python 3.7 dataclasses. Dataclasses allow us to create more structured data than using dicts alone. For instance, each instruction in our internal assembly language has its own dataclass. Pattern matching would make it easy to create readable code which loops over a list of these instructions and performs some sort of optimizations/transformations.<br><br>Finally I want to talk about matching on the structure of built-in data structures like lists and dicts. The javascript proposal does a great job of supporting these data types and I think this would also be natural for Python which also has some destructuring bind support for these types on assignment.<br><br>Consider the example of accessing nested dictionaries. This comes up a lot when working with JSON. If you had a dictionary like this:<br><br><div style="background-color:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid;border-width:1px"><code><div><span style="color:#000">target </span><span style="color:#660">=</span><span style="color:#000"> </span><span style="color:#660">{</span><span style="color:#080">'galaxy'</span><span style="color:#660">:</span><span style="color:#000"> </span><span style="color:#660">{</span><span style="color:#080">'system'</span><span style="color:#660">:</span><span style="color:#000"> </span><span style="color:#660">{</span><span style="color:#080">'planet'</span><span style="color:#660">:</span><span style="color:#000"> </span><span style="color:#080">'jupiter'</span><span style="color:#660">}}}</span><span style="color:#000"><br></span></div></code></div><br>Then trying to access the value ‘jupiter’ would mean one of these alternatives:<br><br><div style="background-color:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid;border-width:1px"><code><div><span style="color:#800"># Risks getting a ValueError</span><span style="color:#000"><br>my_planet </span><span style="color:#660">=</span><span style="color:#000"> target</span><span style="color:#660">[‘</span><span style="color:#000">galaxy</span><span style="color:#660">’][‘</span><span style="color:#000">system</span><span style="color:#660">’][‘</span><span style="color:#000">pl<wbr>anet</span><span style="color:#660">’]</span><span style="color:#000"><br></span><span style="color:#008">print</span><span style="color:#660">(</span><span style="color:#000">my_planet</span><span style="color:#660">)</span><span style="color:#000"><br><br></span><span style="color:#800"># Awkward to read</span><span style="color:#000"><br>my_planet </span><span style="color:#660">=</span><span style="color:#000"> target</span><span style="color:#660">.</span><span style="color:#008">get</span><span style="color:#660">(‘</span><span style="color:#000">galaxy</span><span style="color:#660">’,</span><span style="color:#000"> </span><span style="color:#660">{}).</span><span style="color:#008">get</span><span style="color:#660">(‘</span><span style="color:#000">system</span><span style="color:#660">’,</span><span style="color:#000"> </span><span style="color:#660">{}).</span><span style="color:#008">get</span><span style="color:#660">(‘</span><span style="color:#000">planet</span><span style="color:#660">’)</span><span style="color:#000"><br></span><span style="color:#008">if</span><span style="color:#000"> my_planet</span><span style="color:#660">:</span><span style="color:#000"><br>  </span><span style="color:#008">print</span><span style="color:#660">(</span><span style="color:#000">my_planet</span><span style="color:#660">)</span><span style="color:#000"><br></span></div></code></div><br>With pattern matching this could become more simply:<br><br><div style="background-color:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid;border-width:1px"><code><div><span style="color:#000">match target</span><span style="color:#660">:</span><span style="color:#000"><br>  </span><span style="color:#008">case</span><span style="color:#000"> </span><span style="color:#660">{‘</span><span style="color:#000">galaxy</span><span style="color:#660">’:</span><span style="color:#000"> </span><span style="color:#660">{‘</span><span style="color:#000">system</span><span style="color:#660">’:</span><span style="color:#000"> </span><span style="color:#660">{‘</span><span style="color:#000">planet</span><span style="color:#660">’:</span><span style="color:#000"> my_planet</span><span style="color:#660">}}}:</span><span style="color:#000"> </span><span style="color:#008">print</span><span style="color:#660">(</span><span style="color:#000">my_planet</span><span style="color:#660">)</span><span style="color:#000"><br></span></div></code></div><br>This example was stolen from the tutorial for the glom library <a href="https://sedimental.org/glom_restructured_data.html" rel="nofollow" target="_blank" onmousedown="this.href='https://www.google.com/url?q\x3dhttps%3A%2F%2Fsedimental.org%2Fglom_restructured_data.html\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNF0qrOW9uc3PfYzh-R1jjawKa9Vdw';return true;" onclick="this.href='https://www.google.com/url?q\x3dhttps%3A%2F%2Fsedimental.org%2Fglom_restructured_data.html\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNF0qrOW9uc3PfYzh-R1jjawKa9Vdw';return true;">https://sedimental.org/glom_<wbr>restructured_data.html</a> which works on nested data. Structural pattern matching is a more universal concept and could eliminate the need for these kinds of helper functions.<br><br>From reading through this thread (as well as other background reading like <a href="https://groups.google.com/forum/#!msg/python-ideas/aninkpPpEAw/wCQ1IH5mAQAJ" rel="nofollow" target="_blank" onmousedown="this.href='https://groups.google.com/forum/#!msg/python-ideas/aninkpPpEAw/wCQ1IH5mAQAJ';return true;" onclick="this.href='https://groups.google.com/forum/#!msg/python-ideas/aninkpPpEAw/wCQ1IH5mAQAJ';return true;">https://groups.google.com/<wbr>forum/#!msg/python-ideas/<wbr>aninkpPpEAw/wCQ1IH5mAQAJ</a> and the Javascript proposal) a couple things seem clear to me for pattern matching in the case of Python:<br>- it should be statement based<br>- it should have great support for built-in data types like lists, dicts, namedtuples, and dataclasses<br>- it should form a coherent story with other similar Python concepts like unpacking on assignment<br><br>There are a ton of details to be worked out obviously and we should go slow as Guido suggested. However, I believe that it would be worth doing the work. To that end: if there’s anyone else who’d like to collaborate and come up with a first draft of a more well-defined proposal I would love to commit my time to this, my email is below.<br><br>Also, I sent this email from PyCon in Cleveland if anyone would like to brainstorm in person :).<br><br>Steven Heidel<br>Rigetti Quantum Computing<br><a href="javascript:" rel="nofollow" target="_blank" gdf-obfuscated-mailto="sB8WxXJlBwAJ" onmousedown="this.href='javascript:';return true;" onclick="this.href='javascript:';return true;">ste...@rigetti.com</a><br><br>On Friday, May 4, 2018 at 4:37:43 PM UTC, Guido van Rossum wrote:<blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div>Can I recommend going slow here? This is a very interesting topic where many languages have gone before. I liked Daniel F Moisset's analysis about the choices of a language designer and his conclusion that match should be a statement.<br><br>I just noticed the very similar proposal for JavaScript linked to by the OP: <a href="https://github.com/tc39/proposal-pattern-matching" style="background-color:transparent;color:rgb(3,102,214)" rel="nofollow" target="_blank" onmousedown="this.href='https://www.google.com/url?q\x3dhttps%3A%2F%2Fgithub.com%2Ftc39%2Fproposal-pattern-matching\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNGUC-Lf2nwRG6W9PLcoXj7UghOuYA';return true;" onclick="this.href='https://www.google.com/url?q\x3dhttps%3A%2F%2Fgithub.com%2Ftc39%2Fproposal-pattern-matching\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNGUC-Lf2nwRG6W9PLcoXj7UghOuYA';return true;">https://github.com/tc39/<wbr>proposal-pattern-matching</a> -- this is more relevant than what's done in e.g. F# or Swift because Python and JS are much closer. (Possibly Elixir is also relevant, it seems the JS proposal borrows from that.)<br><br></div><div>A larger topic may be how to reach decisions. If I've learned one thing from PEP 572 it's that we need to adjust how we discuss and evaluate proposals. I'll think about this and start a discussion at the Language Summit about this.<br></div><div><div><br><div>-- <br><div>--Guido van Rossum (<a href="http://python.org/~guido" rel="nofollow" target="_blank" onmousedown="this.href='http://www.google.com/url?q\x3dhttp%3A%2F%2Fpython.org%2F~guido\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNGKI5lSgzXFUM7Y5HtkFAp6sQAxEg';return true;" onclick="this.href='http://www.google.com/url?q\x3dhttp%3A%2F%2Fpython.org%2F~guido\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNGKI5lSgzXFUM7Y5HtkFAp6sQAxEg';return true;">python.org/~guido</a>)</div>
</div></div></div></div>
</blockquote></div></blockquote></div></div>