
On 2018-05-03 15:02, Jacco van Dorp wrote:
# Pattern matching with guards x = 'three'
number = match x: 1 => "one" y if y is str => f'The string is {y}' _ => "anything"
print(number) # The string is three
I think you meant to use isinstance(y, str) ? This looks like an incomplete ternary as well, missing the else clause, so it wouldn't be a valid expression either way. And a NameError. y is never defined anywhere. Since there's no name bound to the variable being matched, would that mean a new keyword ? Also, in the rest you seem to be testing "x == {matchidentifier}", but here it suddenly looks like a boolean True would trigger a match ? And if so, would other boolean truthy values also trigger one, making the entire construct rather....limited ?
It looks like you're attempting to suggest at least 3 new language syntax elements here. 4 if I count the type matching of "x:int", which you could sell as type annotation, if those hadn't been explicitly optional and ignored when actually binding the names.
It's a proposal for new syntax. I suspect that you're trying to read the left-hand side of the match cases as Python expressions. They're a distinct thing: unbound names like 'y' are an essential component of any non-trivial destructuring pattern match, as opposed to an error in an expression. I believe the intention in the example you quoted is syntax something like: <match-case> ::= <pattern> | <pattern> "if" <expression> where the expression is a guard expression evaluated in the context of the matched pattern. IOW, it could be written like this, too: number = match x: 1 if True => "one" y if isinstance(y, str) => f'The string is {y}' _ if True => "anything" I do see a lot of room for bikeshedding around the specific spelling. I'm going to try to resist the temptation ;)
And almost every other example can be solved with a dict and .get(). The remainder uses a dict as match, and still work on if/elif perfectly fine.
How about this? def hyperop(n, a, b): return match (n, a, b): (0, _, b) => b + 1 (1, a, 0) => a (2, _, 0) => 0 (_, _, 0) => 1 (n, a, b) => hyperop(n-1, a, hyperop(n, a, b-1)) versus: def hyperop(n, a, b): if n == 0: return b + 1 if n == 1 and b == 0: return a if n == 2 and b == 0: return 0 if b == 0: return 1 return hyperop(n-1, a, hyperop(n, a, b-1)) Of course the latter *works* (sort of: implementing tetration by recursively adding ones never really works) but it's excessively verbose, it's easy to make mistakes when writing it out, and at least in my opinion it's harder to see what it does. It also raises some small but annoying questions, like "do I use if or elif?", "do I use an if for the last case too?", "do I nest the b == 0 cases?", and, if we had used an if for the last case, what we do if we get to the end anyway.
Also, I'd say "but other people do it" isn't a valid reason for implementation. There's plenty people doing stupid things, that doesn't mean it's a good idea to do it to. If they idea can't stand on it's own, it's not worth it.
From the syntax corner, it also doesn't really look like Python to me.
I agree, but I'm sure someone can come up with something prettier.