To make a medium-size story short: No, I don’t believe so.
To make a medium-size story long: …
Let’s imagine you have a simple situation that generates a function and stores it in an API handle value:
REBVAL *foo = rebDo("function [x] [print x]", END);
What should happen if you tried to use a SET-WORD! in code to assign it to another variable?
rebDo("also-foo:", foo, END);
Perhaps one thinks that looks most like accessing a function through a WORD!
foo. That might imply referring to it by its C variable name would execute it by default. Hence the burden would be upon you to do some kind of trick to “disarm” it, such as:
rebDo("also-foo: quote", foo, END);
However, the idea that referring to the C variable name executes it is not generally what happens. Had you written code as a simple C assignment:
REBVAL *also_foo = foo;
foo would not try to execute, and it can’t. In plain C there’s no opportunity for such a statement to execute arbitrary code. At least in that context, a simple reference to a C variable has to be inert…and its mere appearance does not imply execution.
This means you would bias things the other way. If you wanted an execution, you would use an EVAL.
rebDo("eval", foo, "10", END); // to print 10
This concept feels like it makes sense, because mostly what I see in C code is that the calculation to produce the values has already occurred. You don’t want them to undergo a double evaluation. Consider this:
REBVAL *value = rebPath("a/b/c"); // now value holds an item of type PATH! rebDo("target:", value, END);
Here you’re abstracting through a variable that doesn’t look like a path at all. It seems sketchy to be pulling out “live” behavior when it’s not requested, because think about how the following would act:
value: 'a/b/c ;-- now value holds an item of type PATH! target: value
This provides convincing evidence that access through a C variable should be seen as more akin to picking something out of a Rebol variable via a GET-WORD!. It should be seen as inert to the evaluator on the first pass, and it takes something more than just running the evaluator across it once to get it to execute. You either COMPOSE it into a block and DO it, or use EVAL.
I’m curious about what might be possible notationally for a fast/API-level EVAL:
rebDo(rebEval(), foo, "10", END); // 0-arity a bit confusing rebDo(rebEvalNative(), foo, "10", END); // a bit wordy rebDo(rebEval(foo), "10", END); // unusual but nicer
The last one seems coolest to me, even though it’s “strange”. But EVAL is strange…it takes one argument and then potentially bounces it and keeps on going. This suggests the return result of
rebEval(foo) would not be a finalized REBVAL, rather something that has to be spliced into a rebDo() chain…a new datatype. Such things are tricky, but possible…