Historical Rebol used quoted words (LIT-WORD!) to pass variables to functions, with the idea the function could then later set or get those variables. The quote level was removed under evaluation, meaning the function got a WORD!
rebol2>> whatever: 10
rebol2>> foo: func [var [word!]] [print [var "is" get var]]
rebol2>> foo 'whatever
whatever is 10
But we now have a general rule that quoting insulates whatever you quote from binding. So you have to add the binding, by saying something like foo in [] 'whatever
This isn't the only option, if the callee was willing to receive something other than WORD!. We also have THE-WORD!, which currently evaluates to the bound version of itself.
>> @whatever
== @whatever
>> foo: func [var [the-word!]] [print [var "is" get var]]
>> foo @whatever
@whatever is 10
This gets you the binding you want, but now you have a decorated word, which would be annoying if FOO is trying to do something besides GET/SET the value. Plain words are the norm.
If you wanted an undecorated word, you could use the standalone @ operator... which gives back its argument literally:
>> @ a
== a
@ a
is a little bit uglier than 'a
but not as bad as in [] 'a
>> foo: func [var [word!]] [print [var "is" get var]]
>> foo @ whatever
whatever is 10
But the spacing just throws it off to where it no longer looks like a single argument. And it doesn't look like one because it isn't (e.g. can't fill exactly one slot in the API or a COMPOSE). @ is also a function under the current design (you can redefine it), so calling it incurs some overhead.
Or... We Could Say that @ Things Evaluate And Drop The @
>> @word
== word ; bound
>> @(print "Hello")
== (print "Hello") ; bound
>> @[print "Hello"]
== [print "Hello"] ; bound, less useful as plain block would have done that
This would make @word
and @ word
symmetrical, which is appealing.
But it's at the cost of losing the idea of a category of ANY-WORD! that stays somewhat as-is.
How Big A Loss Is The "Inert" WORD!/GROUP!/TUPLE!/PATH!
In practice, the idea of inert words hasn't lived up to my hopes for them. I thought maybe since they would be shielded from multiple phases of reducing, they might become popular for some kind of enumerated types. But being a bit ugly, that's not materialized.
If it gives you any idea of how not-popular the application has been, I changed the evaluator behavior and it only required one change in UPARSE to boot:
(if spec.1 = '@pending [
assert [spec.2 = [<opt> block!]]
autopipe: false ; they're asking to handle pending themselves
spread reduce [@pending spec.2] ; <-- this has to be '@pending
elide spec: my skip 2
] else [
autopipe: true ; they didn't mention pending, handle automatically
spread [@pending [<opt> block!]]
])
They're still free to be used in dialects for whatever purpose (here we see them marking output parameters in the function spec dialect). And they serve a good purpose in PARSE for "treat this value literally":
>> block: [some "a"]
>> parse ["a" "a"] [block]
== "a"
>> parse [[some "a"] [some "a"]] [some @block]
== [some "a"]
But it seems that with the new binding model, they have a higher calling in the evaluator... for producing undecorated bound things!
If you want wordlike things that do not reduce, there's blank-headed paths like /FOO
("refinement"). They have a binding and can be looked up. Today, blank-headed tuples like .FOO
don't evaluate, but I'm aiming to say that they do--and that they do member lookup in methods. Or... y'know... you could put the word in a block! [foo]
Note That Decorated Types Have To Use @
There's no such thing as a THE-SET-BLOCK! (and I don't imagine there ever will be).
>> @[x y]:
** Error: That doesn't exist
>> @ [x y]:
== [x y]:
So it's only the plain WORD!, TUPLE!, PATH!, GROUP! and (redundantly) BLOCK! that you can do this without a space.
But it's likely much rarer to be generating such material bound in isolation.
In any case, preliminary looking at the results, I think this is a solid change and much needed in the new binding world.