Before there were distinct NULL and VOID states, there was only NULL... and it was the product of failed conditionals. There was a debate about whether NULL should be an error if encountered by REDUCE, or if it should vaporize. This is a little piece of circa 2021 history I extracted about the first case I saw that represented a problem, that I edited out of a thread I was paring down.
Both changes are now in master:
The new REDUCE behavior has been advocated now by @rgchris, @BlackATTR, @giuliolunati, @gchiu, and was my original choice also:
>> append [<a> <b>] reduce [<c> if false [<d>]] == [<a> <b> <c>]
Up until now it has errored to leave the option open, without yet breaking the "N expressions in, N values out" dogma espoused by DocKimbel.
Hmmm...well when I tried bootstrapping the updated executable, here is an example of where NULL vaporizing in REDUCE bit me:
It was some of Shixin's code from rebmake.
if not let suffix: find reduce [
#application target-platform/exe-suffix
#dynamic-library target-platform/dll-suffix
#static-library target-platform/archive-suffix
#object-library target-platform/archive-suffix
#object-file target-platform/obj-suffix
] project/class [return]
suffix: second suffix
I had changed the suffixes in the base class of some objects from BLANK! to NULL. This was in order to be more likely to catch usage problems of those suffixes, when BLANK! is more quiet about many operations (e.g. they will silently append, like classical #[none] would).
NULL provides a gentle sort of alarm...in the sense that it is falsey and can't be e.g. silently appended without an operation converting it to a value. This is good for callsite comprehension.
But with NULL vanishing here, code in this style has problems. I'm not sure there's anything particularly wrong about code in this style. So we still might want to think about this.