UPDATE: I truly, really, honestly hope the final naming is set.
VOID! is the blank antiform, EMPTY-PACK is alternately known as HEAVY-VOID, the VOID? type constraint errors on empty packs (and maybe other packs as well). ANY-VOID? lets you test for either void.
Then GHOST is arity-0 comment, and GHOSTLY makes VOID! and HEAVY-VOID vanish.
Finally
^is the IDENTITY operator, where IDENTITY is a vanishable function... so it vanishes just VOID! and not HEAVY-VOID.Similar ideas apply to NULL where NULL? would error on heavy null, forcing you to use ANY-NULL? if you were interested in either... or NOT if all you really wanted to know was "is this thing falsey".
I had a bit of a revelation updating an answer to @LkpPo's "too many notes" question:
Clarity + Brevity vs. NULL, BLANK, TRASH, VOID...
The revelation was that through a long process of iteration... I'd actually carved things up to where the "weird" states were becoming the "zero" states of families that had clear and separate responsibilities.
For instance, NONE is just an empty splice. If you understand splices in general:
>> append [a b] [c d]
== [a b [c d]]
>> spread [c d]
== \~[c d]~\ ; antiform (splice!)
>> append [a b] spread [c d]
== [a b c d]
Then it shouldn't be any sort of shock to you that an empty splice is a no-op in an append operation:
>> spread []
== \~[]~\ ; antiform (splice!) "none"
>> none
== \~[]~\ ; antiform (splice!) "none"
>> append [a b] none
== [a b]
Maybe you object to the fact that I've named it (or object to the particular choice of name). But regardless of what you call it, it doesn't need a justification. Because it's part of a clearly defined set. It would take effort to make it not exist, vs just letting it do what it naturally does.
The same line of thinking tracks how a separate datatype--a "BLANK!"--became folded into the RUNE! concept of UTF-8 literal forms as a space character. Once you see it, it can't really be unseen. And you don't have to suffer a crisis of conscience about whether it's truthy or falsey or if it should exist... because you accept character literals need to exist, they should be truthy, DEFAULT should not overwrite them, etc. etc.
And it continues on when you think about empty PACK!, which I've been calling "VOID" (but hold that thought...). Let's say you grasp packs and how their concept of decay works...as well as what happens when there aren't enough pack slots to assign variables:
>> [a b]: pack [1 2]
== \~('1 '2)~\ ; antiform (pack!)
>> a
== 1
>> b
== 2
>> c: pack [1 2]
== \~('1 '2)~\ ; antiform (pack!)
>> c
== 1
>> [x y]: pack [1]
== \~('1 '2)~\ ; antiform (pack!)
>> x
== 1
>> y
** PANIC: y is unset
Once you understand this, does it come as any surprise to see the properties of an empty pack?
>> pack []
== \~()~\ ; antiform (pack!)
>> foo: pack []
== \~()~\ ; antiform (pack!)
>> foo
** PANIC: foo is unset
So once again: I don't have to specifically defend empty pack as an invention in its own right. It exists because it would take work to make empty packs not exist.
...This Is Very Satisfying...
...and I think that this is--essentially--what people like @LkpPo or @rgchris were seeking with their "too many notes" complaints. They were asking for a coherent justification for the existence of weird forms that seemed to overlap in function.
Well, here you go. Ta-da!
![]()
But now that we are down to the home stretch there's one little nagging question.
Should antiform blank (what I've been calling "ghost") just be VOID... and empty PACK! have another name... or just have no name at all?
The duality between blank antiforms and empty packs is laid out pretty clearly here:
Why COMMENT Vanishes, but not EVAL of [COMMENT]?
Once that "safety vest" was finally constructed, it opened the door to "nutty" ideas like OPT just returning a blank antiform... but not carrying the ghostable flag on the function, so the safety vest kicks in and you get an empty pack in multi-step operations...
And this makes me feel like it's time to simply bite the bullet:
>> ~
== \~\ ; antiform (ghost!) "void"
>> opt null
== \~\ ; antiform (ghost!) "void"
>> ()
== \~\ ; antiform (ghost!) "void"
>> ~()~
== \~()~\ ; antiform (pack!) "<your name here>"
>> pack []
== \~()~\ ; antiform (pack!) "<your name here>"
; the safety vest case
>> 1 + 2 ()
== \~()~\ ; antiform (pack!) "<your name here>"
So what happens in this safety-vest scenario is that "a non-ghostable function, if it produces void in a multi-step operation, will synthesize an empty pack."
Optional parameters consider both empty packs and blank antiforms to be "nothing".
But... is there a salient name for empty pack in this world, that helps push it up the reification chain a tiny bit (only a tiny bit, because it's still an unstable antiform with no content).
"a non-vanishable function, if it produces VOID in a multi-step operation, will synthesize a _____ in order to prevent vanishing."
What is _____ ?
