commodorejohn wrote:
Yeah, that's kinda what I figured. Mostly I just wanted to avoid having to either create unique names for each definition or store an array of pointers to anonymous definitions if I could hack up something like Smalltalk's "code blocks" instead and leave them in-place, but that may not be particularly feasible here.
Well a "code block" is just a pointer to code, plus an environment. Given that Forth doesn't really have "environments" (the environment, i.e. the stack, belongs to the caller, not the callee), then a code block in the end IS just that -- a pointer.
So, what you want is something that will compile the enclosed code (at, duh, compile time), but when it's "executed", just returns the pointer.
Thus you could "embed" that in to other definitions and simply pass it along.
Something like:
Code:
: invoke ( execute the code vector on the top of the stack ) ... ;
: simpleif ( bool if-vector else-vector -- if bool is true, invoke if-vector, else invoke else-vector )
ROT IF
SWAP INVOKE
ELSE
SWAP DROP INVOKE
THEN ;
: iftest
LAMBDA[ ." if passed" ] LAMBDA[ ." else passed" ] // we now have two code vectors on the stack
2DUP 1 ROT ROT simpleif // should print "if passed"
0 ROT ROT simpleif // should print "else passed"
;
In the iftest word, the LAMBDAs compile their enclosed code, and at runtime they "jump around it", and push the code vector on the stack.
There's no reason you shouldn't be able to do something like that. You may well be able to do this with stock BUILD DOES>, might have to refactor some of the compiling words to work in both situations.
For that vector thing we did before, you could do something like:
Code:
: do-action ( action -- )
>R // Save the action number
LAMBDA[ ... ] // action 3
LAMBDA[ ... ] // action 2
LAMBDA[ ... ] // action 1
<R // restore the action number
PICK // use the action number to pick the action vector from the stack
INVOKE ;
This isn't quite an "ON GOSUB" or a "CASE" statement, on the surface they look like that, but implementation wise it's quite different.
But you get the gist.