Name shuffle: EVAL => INLINE, DO/NEXT => EVAL/SET


#1

The re-imagining of DO/NEXT is on its way to working. But we clearly don’t want to call it DO/NEXT anymore. (I’m not as much concerned about changing the meaning of DO/NEXT in an incompatible way as I am that I don’t like one version of DO returning an evaluation product, while another returns a series position–that’s confusing.)

The old parameterization of DO/NEXT–where it puts the updated series position into a variable passed by reference and returns the evaluation product–has to die. It’s an incomplete interface in a world with “invisibles”. We don’t want it.

What I think the best idea to do is to call the routine EVAL. “A DO of a BLOCK! is the result of several successive single EVAL steps in the evaluator.” That seems nice.

Concept here is that plain EVAL won’t give you a result, it will just run code and toss the evaluative by-product:

>> code: [print "hi" 1 + 2]

>> eval code
hi
== [1 + 2]

>> eval code
== []

>> eval code
;-- null

If you want the evaluative result, you’d use EVAL/SET. So a typical DO loop might look like:

while [block: try eval/set block 'var] [
    ...
]    

(Remember, you are responsible with pre-loading var with a value–or null–that you want to correspond to what var would be if it happens to never successfully run an eval/set. Sometimes this is best to be #[void], sometimes null, or whatever the circumstance calls for.)

But the current EVAL also exposes a single evaluator step. It’s a weird interface that runs “inline”… it takes one ordinary argument that’s the head of the evaluation, and then gets its arguments from the callsite:

>> eval :add 1 2 ;-- historical EVAL
== 3

>> eval quote x: 100 ;-- historical EVAL
>> print x
100

I’ve been wondering though if maybe we should call this INLINE. Because really that’s what you’re asking it to do…it isn’t so much that the EVAL function is taking arguments and “running a single evaluator step”. It is splicing the material into the stream of execution.

>> x: quote foo:
>> inline x 100
>> foo
== 100

A little bit quirky but it seems to make sense. And it offers the advantage of DO/NEXT not being a parameterization that has to accept everything DO does. (Does do/next http://example.com/script.reb 'pos actually make sense? Can everything that offers a DO interface guarantee that it meaningfully can give back a position into the thing that was done? Or that it even should–it may violate encapsulation…)


#2

Hm. One thing I don’t like about changing EVAL is the API effect.

Right now there are rebEval() and rebUneval() which are a nice pairing for bringing an “inert” value cell to life.

 REBVAL *word = rebRun("quote foo", rebEND);
 rebElide("print", word, rebEND);

By default, that would just print foo the word. Because values are inert…for practical purposes in the API you consider the “word lookup” parallel to be the step that the C code does to get foo out of the word variable. It would feel like double-evaluation if you were to then have the foo get looked up as a word again.

There’s been a convenience in the API, rebEval() for this:

rebElide("print", rebEval(word), rebEND);

It’s common enough I was thinking it might even become rebE() for short.

If it gets changed to rebInline(), then that’s longer and a bit more awkward. Also rebI() is taken as the shorthand for auto-disposed integer constants.

But furthermore, the complementary operation is rebUneval(), which generates “unevaluated versions” of values…e.g. something that when evaluated will give you the value back. This allows you to put things like NULLs–which aren’t legal in BLOCK!s, into blocks as null the word…or functions as (quote :add), etc.

UNEVAL strikes me as a nice name for that. UNINLINE or OUTLINE or other things seem not as good.

So maybe the thing I want to call EVAL above needs another name. GROK? :slight_smile:

Both techniques can make sort of an argument of being a single evaluator step. Since Rebol likes full words, it could be EVALUATE is the actual full exposure of the evaluator:

while [block: try evaluate/set block 'var] [
    ...
]    

That’s not terrible. 8 characters isn’t the end of the world (consider that even SET-WORD! is 9).


Blocks vs Variadics as Dialect Formats