Note that NIHIL is only ignored in "interstitial slots". If you try to call a function that isn't expecting a NIHIL and pass it as an argument, that's an error:
>> append [a b c] 'd comment "ignored"
== [a b c d]
>> append [a b c] comment "not ignored" 'd
** Script Error: No value in antiform BLOCK! pack: ~[]~ (nihil)
At one point in time, the second worked. For an understanding of why it no longer does, see:
Invisibility Reviewed Through Modern Eyes
Void is used generically in many places when you want things to vanish:
>> compose [<a> (if false [<b>]) <c>]
== [<a> <c>]
Allowing NULL to vanish here would be too liberal and not reveal what were likely errors. If you have something that may be NULL that you want to convert to a VOID if so, you can use MAYBE.
VOID is also is used for opting out of things, using the "void-in-null-out" strategy. Compare:
>> block: ["a" "b"]
>> unspaced block
== "ab"
>> to word! unspaced block
== ab
With:
>> block: []
>> unspaced block
== ~null~ ; anti
>> to word! unspaced block
** Script Error: to expects [~void~ element?] for its value argument
>> maybe unspaced block
== ~void~ ; anti
>> to word! maybe unspaced block
== ~null~ ; anti
With:
>> block: null
>> unspaced block
** Script Error: unspaced expects [~void~ text! block! the-block! issue!]
for its line argument
>> unspaced maybe block
== ~null~ ; anti
>> to word! maybe unspaced maybe block
== ~null~ ; anti
Historical Redbol had a lot of people asking that things give NONE! back when they took NONE! in, and this "none propagation" was messy in terms of leading to whole chains which would opt themselves out without knowing where the problem was. Void-in-null-out encourages being more purposeful--you only throw in the MAYBE where you need them.