(Suggested background reading on "what is a literal in a language where every element of source code can be taken literally?")
Let's imagine someone proposed a behavior in Rebol2, where seeing a number "literally" in the parse rule would act like a repeat rule, while using it fetched from a variable would try to match the literal INTEGER!.
rebol2>> parse "aa" [2 "a"] ; since 2 is directly in rule, act as repeat count
== true
rebol2>> count: 2
rebol2>> parse "aa" [count "a"] ; interpreted as looking for literal 2
== false
rebol2>> did parse [2] [count] ; again looking for literal 2
== true
There's clearly something a bit confusing about this. But is it always bad?
Clearly not Always Bad, Consider WORD! Fetch...
Just look at how PRINT handles the word FOO "literally", and then how it acts when it is fetched via VAR:
>> foo: ~
>> print ["a" foo "b"]
** Error: foo is unset
>> var: 'foo
>> print ["a" var "b]
a foo b
We wouldn't want to say that print ["a" var "b"]
is chained to behaving the same as if FOO had been literally in the block. That would be nonsense.
So we have at least one example in defense of the idea that there's no hard rule saying that when you access something via a fetch it has to act as if the fetched thing was written in that place.
Generic Quoting Is A Powerful Tool
Historical Rebol only had LIT-WORD!:
rebol2>> print ["a" 'foo "b"]
a foo b
But dialect authors should rejoice, as Ren-C has QUOTED! for any value type (including something already QUOTED!), and QUASI! for isotopes. This is heavy artillery.
As a general rule, I believe dialects are stylized to act on variable fetches should make the handling of QUOTED! act just like if a variable had unfetched the quoted thing.
So if you have variables or expressions that act like this:
>> var
== <X>
>> (some expression)
== <X>
The expression behaviors should give the same answer, on potentially a subset of the literal forms:
>> dialect [... '<X> ...]
== <Y>
>> dialect [... var ...]
== <Y> ; or error if non-literal use is suspect
>> dialect [... (some expression) ...]
== <Y> ; or error if non-literal use is suspect
Don't forget that the quoting behavior in COMPOSE makes getting those quote marks on easy when building dialect blocks:
>> compose [... '(var) ...]
== [... '<X> ...]
>> dialect compose [... '(var) ...]
== <Y>
So Now... Back To What If It's not Quoted...
-
I've offered the plausibility that dialects could by default reserve QUOTED! behavior to be a superset of what would happen if the unquoted item were fetched from a variable or a product of expressions.
-
I've shown that plain WORD! is a kind of tautological example of a datatype in dialects where the fetched result does not act like the original WORD! value it was fetched from.
- We can extend this to however our dialect evaluates expressions, e.g. from GROUP!s or BLOCK!s, or just inline as a DO/NEXT step.
...does this mean that other behavior variances between non-quoted dialect elements and their fetched form are fair game--as with the deviating behavior of INTEGER! in PARSE proposed at the top of this post?
Pertinent Case Study: BLANK! As Nothing vs. Nothinglike-Thing
BLANK! has something of a split personality, from its dual nature of being a "reified concept that stands for nothing".
Some cases could really benefit from it meaning something. For instance, I've consistently wanted it to mean space
in DELIMIT's "dialect" :
write port unspaced [
"HTTP/1.0" _ code _ code-map/:code CR LF
"Content-type:" _ type CR LF
"Content-length:" _ (length of body) CR LF
CR LF
]
That is awesome. It lets you see what's going on very clearly. I'm always annoyed when people include spacing in the edges of the things being spaced, like "HTTP/1.0 "
... because it makes it harder to factor. It also makes it hard to see what's a string and what's not:
print [" At a " glance " how " do " you tell " whats " a string "]
But it could potentially sucks if a variable holds BLANK! with the intent to mean nothing if that nothing becomes a space character.
To demonstrate how it sucks, let's say you've got a situation like this where the second item is supposed to be conceptually "not there":
values: ["one" _ <three>]
print "And here the values are!"
for-each item values [
print [item]
]
When a fetched BLANK! is allowed to act as a space, you get something that's actually worse than it looks:
And here the values are!
one
<three>
I say it's worse because that empty line isn't actually empty. It actually wrote a space and a newline.
So what if things like PRINT/UNSPACED would only treat a "literal" blank as a space?
>> unspaced ["a" _ "b"]
"a b"
>> var: _
>> unspaced ["a" var "b"]
** Error: Can't Turn Evaluative BLANK! Into Space
>> unspaced ["a" maybe var "b"]
"ab"
>> unspaced compose ["a" (var) "b"]
"a b"
On the surface, that seems pretty reasonable. Trusting that you know what you're doing in the COMPOSE case makes sense, because you could be putting WORD! or arbitrary code in there...so if you got BLANK! you must have meant it.