3 ms·
It’s neat that Python allows writing such things, but it’d be nice to see what the effect on debugging and stack traces are before writing anything with it.
by marmaduke 8y ago
It’s neat that Python allows writing such things, but it’d be nice to see what the effect on debugging and stack traces are before writing anything with it.
- bjoli 8y agoPattern matching is actually not very hard to write. There is a portable pattern matcher for scheme that uses macros to provide high quality code generation. In guile the module (ice-9 match) generally has zero runtime cost compared to equal hand-written code.
- marmaduke 8y agoThis may be true but misses my point: when I navigate a stack trace and try to figure out how execution went through this match process, it will be more difficult to understand than idiomatic Python code, because the tooling is line-oriented. Good FP debuggers would be able to step through it of course so it can be restated as a “toolchain issue” but that ignores the fact that Python is largely statement oriented, in terms of its execution model.
- bjoli 8y agoSorry, I should have been clearer. The macro way of doing it doesn't mess with stack traces as it expands to pretty clean scheme code, at least after the optimizer has had it's way. I am sad that most languages don't have macros since it is a very powerful tool. Not only does it let you abstract the ugliness away from approaches like this python one (which is actually pretty decent), but it also let's you produce good machine code from a "bolted on" construct. The python matcher is bound to have some overhead, whereas a syntactically expanded one is not.
- marmaduke 8y agoAh I see what you mean (I wrote macros in Clojure years ago). Yep that would do it, but would require an AST-rewriting decorator in Python.
- uranusjr 8y agoThat’s an interesting thought! I guess I just found a good project to play on during the holidays. I wonder if something like this would work: with matching(expr) as m: @m(pattern) def do_for_pattern(v): ... @m(_) def catchall(v): ...
- btown 8y agoOoh that is a really nice syntax. And it would definitely work as it is essentially: m(pattern)(lambda v: ...) Design would be to consider the execution of the match and dispatch as a “cleanup” of the specification created in the block. Which makes a ton of sense in a weird way. May end up using this, or one of us should send a PR to the OP!
- b3orn 8y agoSomething like this? class matching: def __init__(self, expr): self.expr = expr self.patterns = [] self.result = None def __call__(self, pattern): def _inner(func): self.patterns.append((pattern, func)) return func return _inner def __enter__(self): return self def __exit__(self, *args): for pattern, func in self.patterns: if pattern.match(self.expr): self.result = func(self.expr)