Clarity + Brevity vs. NULL, BLANK!, "NONE!", "VOID!"

(2022 note: This question from 2019 and response were lifted out of a thread that was otherwise outdated enough to warrant deleting...trying to update the answer.)

@hostilefork says:

I think any illusions of Ren-C being able to bring evaluator "safety" to a fundamentally unsafe language are being stripped away with time. Instead, what's actually happening is that the features are getting laser-calibrated to where an informed programmer can write short, correct, code easily... the right thing is the short thing, not something riddled with edge-case handling.

Clarity is a catalyst for safety in a language. But beyond that, the bias seems tipping ever toward being clean and powerful enough to "make your own you-made-a-mistake-catching-safety mechanisms"...

Clarity and brevity are two fundamental qualities of good writing. I think that applies to programming as well. Also 4 concepts so close (NULL, BLANK!, NONE! and VOID!), make me look for a fundamental problem in the language, or they do not have adequate names.

I do not quite understand the usefulness of these 4 variants but should not there be one, or several but named to make understand to which functionalities of the language they relate (block, value, refinement ...)? Maybe I get it wrong.

NONE! was a Rebol2-ism (along with UNSET!), and does not come up in Ren-C except in "Redbol" emulation.

So what I describe is how these two ideas have become three:

  • NULL has properties unlike anything in Rebol2. It is not a "value" at all (and type of a null is also a null). It cannot be put in a BLOCK!. It is a transitional state representing nothing, like how a C null pointer doesn't point to any memory. It is conditionally false if it appears in something like an IF statement, and it is the result of any control construct that does not run a branch...or any looping construct that BREAKs. ELSE and THEN react to their left-hand-side being null or non-null, respectively.

  • BLANK! is a unit type...e.g. a value of type blank holds no further information (than that it is of type blank). Unlike NULL it's something that can appear in a block, and hence can be used as a placeholder--for instance if a block represents a record structure broken into N-element units, it could represent a missing field. Values of this type are conditionally false.

  • What was once called "VOID!" has morphed into something more nuanced, known as the BAD-WORD!...which can exist in forms known as "isotopes". This is a necessary complexity whose explanation does not fit in this post. :slight_smile: But today's idea of VOID--as promoted by rgchris--isn't as a type at all, but to capture invisibility; I think this makes sense, e.g. 1 + 2 something-returning-void is 3.

Rebol2's NONE! and Ren-C's BLANK! were always supposed to be quite similar, just a different name. But NULL has taken over many of the duties of NONE! as an indicator of "soft failure" from a when a FIND can't find anything, or a conditional statement doesn't run any branches. BLANK! sticks around as the solution to the problem of neutral placeholders in blocks.

I think the names work pretty well. Particularly pleasing is that NULL is exposed in the API as C and JavaScript's NULL. That has turned out to be very important.

Rebol2 always had trouble with #[none]-the-unit-value and none-the-word, frequently rendering it as looking like the word:

rebol2>> find [a b c] 'd
== none

As mentioned, Ren-C does that with NULL now...which is better.

But reserving plain old _ so it's the literal form for a placeholder...and having it be named BLANK!...has felt pretty good. But we're still in that stretch of time for evaluating decisions for their merit...