<div dir="ltr">Structural pattern matching should address the following, somewhat similar to regex pattern matching:<div><br></div><div>1. Patterns are quoted. This can be implicitly done, because of built-in syntactic support; or one is supplying the pattern to a library using regular Python quoting.</div><div><br></div><div>2. Patterns should support bind variables for the unpacking. In languages like Scala, this is very natural to do, with bop, v1, v2 lexically scoped to the RHS of =>.</div><div><br></div><div>```scala</div><div>case Binary(bop @ (Lt|Le|Gt|Ge), v1, v2) if isValue(v1) && isValue(v2) =></div><div>   doreturn(B(inequalityVal(bop, v1, v2)) ) </div><div>```</div><div><br></div><div>This is an example from an interpreter used in a lab exercise in a class I teach, with patterns against ASTs. The ASTs are themselves defined in terms of Scala's case classes, which are more or less equivalent to namedtuples in Python.</div><div><br></div><div>Clearly the scoping of bind variables can be emulated by the match object, much as we do in regexes, at the cost of some minor overhead.</div><div><br></div><div>3. Some protocol to connect together objects like tuples, namedtuples, and arbitrary classes with the matching. In Scala, this is called unapply, and given that Scala has similar object-oriented aspects that are similar to Python in making life more difficult ;), when compared to Haskell's comparatively simple rules, it's probably close to what we need to do for __match__ or something like that.</div><div><br></div><div>The challenge is making this work together, especially distinguishing patterns from bind variables. Haskell makes it easy by a requirement that algebraic types have constructors which start with an upper case letter. Scala can do simple scope analysis of names to determine if it's a case class or a bind variable. For Python, presumably more syntax is necessary in the pattern specifier. Maybe something like the following, which seems unambiguous, possibly not so ugly:</div><div><br></div><div>```python</div><div>case Binary(bop @ (Lt|Le|Gt|Ge), v1@, v2@) if isValue(v1) and isValue(v2):</div><div>   # bop, v1, v2 are lexically scoped here</div><div>```</div><div><br></div><div>Am I missing anything? It seems to me that one can do structural pattern matching as a library (do obvious changes to above); although having it supported with specific syntax might make it much nicer.</div><div><br></div><div>- Jim</div><div><br></div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, May 24, 2016 at 11:42 AM, Koos Zevenhoven <span dir="ltr"><<a href="mailto:k7hoven@gmail.com" target="_blank">k7hoven@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">On Tue, May 24, 2016 at 5:59 PM, Michel Desmoulin<br>
<<a href="mailto:desmoulinmichel@gmail.com">desmoulinmichel@gmail.com</a>> wrote:<br>
> What about making it a function ?<br>
><br>
> Pattern matching is complex, it can be like a mini language inside the<br>
> language, just like regex.<br>
><br>
> To match text we do:<br>
><br>
> import re<br>
> re.match('pattern', 'string')<br>
><br>
> We could do the same for matching structures:<br>
><br>
> from inspect import match<br>
><br>
> def do(stuff):<br>
>     m = match(stuff): # m implements __call__<br>
>     if m('whatever mini language you like'):<br>
>         return foo<br>
>     if m('again'):<br>
>         return m.thing_your_extracted<br>
><br>
<br>
</span>Or with methods:<br>
<br>
m = match(stuff)<br>
if m.by_type(SomeType):<br>
    # handle SomeType<br>
elif m.by_attrs('x', 'y'):<br>
    # do things with stuff.x and stuff.y<br>
elif m.by_len(3):<br>
    x,y,z = stuff<br>
    # do things with x, y, z<br>
<span class=""><br>
> Pros:<br>
><br>
> - no need for a new syntax<br>
> - very explicit<br>
> - use well know constructs<br>
> - we can easily start experimenting with the matching language in a lib<br>
> in Pypy<br>
</span>+ can be extended easily<br>
<span class=""><br>
><br>
> Cons:<br>
><br>
> - much more verbose;<br>
> - debugging your mini language and handling error is not as good;<br>
</span>+ probably slower<br>
+ need to separately get the desired attributes/elements after matching.<br>
<span class="HOEnZb"><font color="#888888"><br>
-- Koos<br>
</font></span><div class="HOEnZb"><div class="h5">_______________________________________________<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/mailman/listinfo/python-ideas</a><br>
Code of Conduct: <a href="http://python.org/psf/codeofconduct/" rel="noreferrer" target="_blank">http://python.org/psf/codeofconduct/</a><br>
</div></div></blockquote></div><br></div>