2 ms·
I think the general concept described here is great, but I feel the description is lacking a bit. I find the description is imprecise and suggests some things a
by noelwelsh 3y ago
I think the general concept described here is great, but I feel the description is lacking a bit. I find the description is imprecise and suggests some things are hard that I don't think are difficult.
What is being described is a basic tree walking interpreter. If this is new to you, and you come from the OO world, there is an extended description in https://craftinginterpreters.com/a-tree-walk-interpreter.html https://craftinginterpreters.com/a-tree-walk-interpreter.htm...
In the FP world this very very (very!) standard. A tree walking interpreter is one hop away from FP basics. The tools you need are tools that beginners learn in their first few weeks:
1. algebraic data types to represent the abstract syntax tree; and
2. structural recursion (usually implemented via pattern matching) to walk over the algebraic data type and interpret it.
Using generalized algebraic data types is a small extension if you don't want to box your result types (which addresses the comment "Python's duck typing definitely helps make your life simpler, because otherwise you need to be careful about designing what all the Eval()s return." in the OP.)
I don't understand why OP says conditionals or control flow are difficult. Those have been straightforward in the interpreters I have created.
Overall, I feel there are standard techniques for this kind of thing, in both the OO and FP worlds. In my experience the FP world is more precise with terminology, and I think this is beneficial.
- Joker_vD 3y agoThe only truly difficult control flow to implement is unrestricted goto. Conditionals/loops/function invocations are trivial at best, slightly annoying (due to juggling the scopes/environments) at worst.
- thatcks 3y agoAs far as I can see, generalized control flow complicates the situation because you need to propagate a variety of signalling results up the tree. Consider a for loop with a switch inside of it, inside of which is an if with a return; if you hit that return, you need to propagate 'return from the function with this result' out through the containing if, switch, and for loop, which means that the Eval() or equivalent for each of them probably all need to know about all of your early-return options (since a 'break' is different from a 'return', especially if you support multi-level breaks). (I'm the author of the linked-to article.)