patternMinor
Lazy concatenative functional language
Viewed 0 times
functionallazyconcatenativelanguage
Problem
Can the idea of concatenative programming languages be extended to call-by-need evaluation strategy?
I see some problems that I will explain with few examples. I will use a prefix instead of a postfix notation, so evaluation takes place from left to right.
Duplicate an argument seems trivial:
However, we can not forget that A is unevaluated, so the previous example only work for literals or quotations, but not for unevaluated code:
This can be solved in two ways. First, we can impose some structure (unflat) to the code based on the functions arity in the parsing stage:
The problem with this approach is that we lose all the benefits of concatenative programming (for example, flatness and multiple return values). In fact, we are converting function composition to function application in prefix notation... In this case:
Naively translates to:
But it result in an strict language is:
The second solution is to instruct the evaluator to reduce the stack just enough to get as many arguments as the current word needs:
Looks good, but the target of lazy evaluation is to evaluate arguments only when needed. In this case we are evaluating
What contradicts the expected call-by-need semantics:
I see some problems that I will explain with few examples. I will use a prefix instead of a postfix notation, so evaluation takes place from left to right.
Duplicate an argument seems trivial:
drop A B -> BHowever, we can not forget that A is unevaluated, so the previous example only work for literals or quotations, but not for unevaluated code:
drop 123 B -> B
drop "abc" B -> B
drop [+ 1 2] B -> B
drop + 1 2 B -> 1 2 B -- NON SENSE!This can be solved in two ways. First, we can impose some structure (unflat) to the code based on the functions arity in the parsing stage:
drop + 1 2 B -> drop [+ 1 2] B // at parse time
drop [+ 1 2] B -> B // at run timeThe problem with this approach is that we lose all the benefits of concatenative programming (for example, flatness and multiple return values). In fact, we are converting function composition to function application in prefix notation... In this case:
dup + dup 2 3Naively translates to:
dup [+ [dup 2] 3] -> dup [+ 2 2 3] // `+` arity mismatch. What to do with the extra value? Which one is it, 2 or 3?But it result in an strict language is:
4 4 3The second solution is to instruct the evaluator to reduce the stack just enough to get as many arguments as the current word needs:
drop + 1 2 B -> drop 3 B -> BLooks good, but the target of lazy evaluation is to evaluate arguments only when needed. In this case we are evaluating
+ 1 2 needlessly. It is not a big problem until we found:drop + bottom 2 B -> bottomWhat contradicts the expected call-by-need semantics:
drop + bottom 2 B -> BSolution
It can be done. Here's a presentation explaining the language and how the compiler works (so far).
You can play with an asm.js version at http://hackerfoo.com/eval.html
You can play with an asm.js version at http://hackerfoo.com/eval.html
Context
StackExchange Computer Science Q#65806, answer score: 6
Revisions (0)
No revisions yet.