On Fri, Apr 18, 2014 at 9:54 PM, Andrew Barnert email@example.com wrote:
Meanwhile, ML and friends let you go farther, matching by partial values:
of (True, y): process(y) of Eggs(z): fry(z)
The first matches only if it's a tuple of exactly two values and the first is equal to True, binding y to the second; the second matches only if it's equal to an Eggs instance constructed with exactly one argument, and binds z to that argument.
Clearly not all of this fits into Python. (The last example isn't even conceptually possible, given the way object initialization works.) But it's worth considering what does and what doesn't fit rather than trying to design a feature without even knowing what the options are.
I'm really glad you brought this up, and it isn't conceptually impossible. Eggs(x) inside a pattern probably won't actually initialize an Eggs object; it probably would create a pattern object instead, and the value being matched can decide whether or not it obeys that pattern, and (if so) what object should be assigned to z.
Why is it that every time someone brings up switch/case, they're being inspired by C and Java instead of ML or Haskell? People are looking backwards instead of forwards. Python doesn't have a nice way of pattern matching on tagged unions in general, not just C-style enums -- and it really ought to. I think pattern matching could fit in Python, where switch doesn't really. Switch replaces if/elif, pattern matching replaces the if/elif plus any work unpacking contents. The format of a pattern match encourages code to be written in a way that disjointly separates groups of disparate values, in a way that isn't difficult and doesn't involve weird type checks or whatever.
Looking at the difference in e.g. AST manipulation code with/without is a nice example of how code can be made more readable. And looking at the problems Python code has today with this kind of thing is also illustrative -- for example, how do you tell the difference between no result, and a result whose value is None? In some APIs, you can't (!), in some, you need to specify a special sentinel object and check identity (ew), and in some, no result is represented by an exception -- which is fine, but in some cases very error prone (an uncaught StopIteration, for example, will terminate any generator that calls you, which can be difficult to notice.) Pattern matching offers a real alternative option here that wasn't realistic before.
But, maybe this is one of those things that won't happen because Haskell licked the cookie and now everyone thinks it's gross and unreadable, and can't be convinced otherwise. I'm more worried that people don't even know this exists...