I just had a bug that was rather frustrating to find. I changed:
foo: func [
{Description}
param [...]
/refine
][
...
]
into:
foo-core: func [
{Description}
param [...]
/refine
][
...
]
foo: adapt 'foo-core [
{Description}
][
...
]
But ADAPT doesn't take two parameters. I should have eliminated the "spec" block from the ADAPT entirely, but I only deleted the parameters. This effectively gave me:
foo: adapt 'foo-core [
{Description}
] ; "spec" block treated as the adapt "prelude"
[...] ; stray random block, thrown out
There's no warning in this case, because a plain BLOCK! evaluates to a plain BLOCK! and gets thrown out.
There's nothing we can do. Or... is there?
This kind of thing almost always represents an error. This got me to wondering about generalized quoting. Might it help us?
What if plain unevaluated BLOCK! was an error in evaluation if it was not a parameter to anything, and not a result of anything...?
So maybe this would be an error:
all [
a = b
c = d
[this block does nothing]
]
But this would not:
data: all [
a = b
c = d
[assignment target, it's okay]
]
And this would also be fine:
foo: func [return: [block!] a b c d] [
all [
a = b
c = d
[result of function so it gets used]
]
]
Maybe quoting could let you subvert the rule:
all [
a = b
c = d
'[just throw this out, don't complain]
]
Note COMPOSE has power for this kind of thing built-in:
block: [thing to throw out]
data: all compose [
a = b
c = d
'(block) ; the tick would also suppress ACTION! evaluation, etc.
]
I don't know if the QUOTED! exemption is necessary or not, because this could run into problems as well of throwing out a quoted thing.
Challenge: when is non-evaluation utilized?
There's been some play with the fact that things don't evaluate to make constructs that have markup in them. Think of for example a modification of EITHER that lets you label the branches:
my-either condition [<tag> ...code...] [<tag> ...code...]
Skipping the tag silently might be considered a feature, because the code is looked at. I don't know, maybe having to skip that tag before executing is better practice.
Just asking the philosophical question here of "why is throwing away inert interstitial expressions of great value". We have ELIDE and COMMENT. Might we do more for the sanity of the language if we noticed and errored if values were being silently discarded?
Usually trying to implement a rule like this shows problematic cases, but I tend to write it up as a way of seeing if I can talk myself out of it by coming up with a disproof before bothering to try writing it...