At the moment, not all antiform states have meanings.
It is likely the case that you should be disallowed from creating ones that don't have meanings, to reserve them for future use.
(Update: These are now called KEYWORD!)
I wrote about the boolean design in a separate post.
It may be that these are narrowed to only a small set of choices reserved by the system like ~null~ and ~okay~... and if you want a generic error-trigger (like a labeled unset variable) that would be something else, like an antiform rune!
Sorry, yes, this has changed a lot.
As of the current (and hopefully final) edit I have to make to this post about it: TRASH is the state of unset variables, and is an antiform space
(If you find posts with outdated naming let me know--just leave a reply citing the problem and I will fix it up.)
Non-antiform frames don't trigger execution via word reference, are easier to pass around and manipulate.
>> f: make frame! append/
== &[frame! ...]
>> f.value: 10
== 10
>> append10: anti f
== \~&[frame! ...]~\ ; antiform (action!)
>> append10 [a b c]
== [a b c 10]
A non-antiform frame--by virtue of not being an antiform--can appear literally in a block and the evaluator will run it when encountered, without the need for a word reference to trigger it.
>> eval compose [(f) [a b c]]
== [a b c 10]
Due to this design, enumerating blocks will not accidentally run functions, the way historical Rebol and Red will:
rebol2>> foreach item compose [(:append) (:insert) (:change)] [
if action? item [print "it's an action"]
]
** Script Error: item is missing its value argument
...since only antiform actions run via word reference, and there are no antiforms allowed in blocks.
NIHIL is the name for the special case of antiform BLOCK!, which is a parameter "PACK". It's simply an antiform block with no values in it.
I've mentioned previously that packs are the basis of multi-return values, but if a situation is not sensitive to multi-returns then they will decay to their first element.
>> x: ~['1 '2]~ ; packs hold lifted values
== 1
>> [x y]: ~['1 '2]~
== 1
>> x
== 1
>> y
== 2
>> append [a b c] ~['1 '2]~
== [a b c 1]
As an example of the usage of multi-return values, consider FIND.
>> find "abcdefghi" "def"
; first in pack of length 2
== "defghi"
>> pos: find "abcdefghi" "def"
== "defghi"
>> [pos end]: find "abcdefghi" "def"
== "defghi"
>> end
== "ghi"
NIHIL being zero values long cannot be used in an assignment, but if it's between expressions it will vanish.
>> 1 + 2 ~[]~
== 3
This is used as the return value for things like COMMENT and ELIDE.
Antiform commas (like antiform frames) cannot appear in blocks, so certainly different in that respect.
>> length of [10 + 20,]
== 4
>> 10 + 20,
== 30
Antiform ERROR! is a "Raised" Error
If you look at exception handling in Rebol and Red, it is extremely brittle. Their constructs will basically intercept any failure that occurs at any level in the enclosed code... including typos:
As a very simple example:
red>> attempt [data: read http://example.com]
== {<!doctype html>^/<html>^/<head>^/ <title>Example Domain</title>^/^/ ...
red>> attempt [data: read http://xaasdfaefafa.com]
== none
red>> attempt [data: readd http://example.com]
== none
So there's no real way to narrow intercepting errors that are a result of a specific call. Ren-C uses error antiforms to do this... where you can't store error antiforms or pass them most places, but special constructs like TRY and EXCEPT can handle them.
e.g. TAKE returns an error antiform when you try to take from an empty block. By default this will be "promoted to failure":
>> take []
** Script Error: Can't TAKE, no value available (consider TRY TAKE)
But before that promotion to failure (which can only be intercepted by SYS.UTIL.RESCUE), you can lift an ERROR! at the moment it is returned from a specific call:
>> lift* take []
== ~&[warning! [
type: 'Script
id: 'nothing-to-take
message: "Can't TAKE, no value available (consider TRY TAKE)"
near: [lift* take [] **]
where: [take console]
file: ~null~
line: 1
]]~
As it suggests, TRY will convert ERROR! antiforms to null:
>> try take []
== \~null~\ ; antiform
Original writeup here:
PANIC vs. RETURN FAIL: The Age of Definitional Errors!
Antiform OBJECT! is the very experimental "LAZY"
This has turned out to be more of a rabbit hole than I first thought. I'm not sure if this is going to make it, but some experiments have been done with it:
Applications of Isotopic Objects