Why NOTHING Is The Name For The "Unset State"

As isotope design became refined, I became very pleased with the choice for what unset variables hold being the antiform blank.

>> x: ~  ; evaluating quasiform blank gives antiform blank (no console display)

>> unset? $x
== ~true~  ; anti

The alternative of using the antiform word! ~unset~ was available. But antiform blanks are a particularly pleasing choice, due to their succinct representation...which helps assigned variables stand out better in lists of mostly-unset variables. And it's hard to think of what antiform blanks would mean if they were not the unset state!

Also, if ~unset~ were used then people would probably expect unset? ~unset~ to be true. But I've held pretty strongly to my general terminology:

"There is no such thing as an 'unset value'. But variables can be considered unset...when they hold a value that is an antiform blank."

I'm pleased with this and have almost no complaints.

The problem is that ANTIFORM-BLANK is a mouthful. It needed a short name.

JavaScript Don't Care

JavaScript went with the idea that unset variables hold "undefined", and you can test for it using the typeof operator to subvert the error that is raised on access for variables that are never declared (what we might think of as unbound):

>> typeof asdf == 'undefined'
<- true

But if you define a variable, then it will retrieve the undefined state without error:

>> let jkl
<- undefined

>> jkl
<- undefined

Whatever. Point is, they don't have any crisis of conscience on whether "variables are undefined, not values". They just go with it, as historical Redbol did with UNSET!.

But I don't like it.

NOTHING Came To Seem The Best Option

For a while I thought I was settled on calling it "trash". I suggested it way back when the unset state was being changed away from being called VOID.

But then I realized that this was a much better name for QUASIFORM-BLANK (the tilde) than it was for the ANTIFORM-BLANK.

This led me to realize that NOTHING was the right answer.

  • TRASH evaluates to NOTHING ("when you take out the trash, you're left with nothing")

  • A variable that is unset holds NOTHING

  • META of NOTHING is TRASH

  • If a function evaluates to NOTHING, the Console has nothing to display

I had some initial reluctance about verbose names:

foo: func [
    return: [nothing?]
    bar [block!]
][
    append bar [a b c]
    return nothing
]

But there's a reasonable answer in the modern type checking world for these cases which is semiotically consistent... use a tilde (trash). The type spec accepts it (and assumes you mean an antiform), and RETURN will accept it (where the evaluator will turn the quasiform into an antiform):

foo: func [
    return: [~]
    bar [block!]
][
    append bar [a b c]
    return ~
]

As it happens, the default return result from functions is nothing. I've also proposed it might be good to make the assumption that a function without a RETURN: spec is a procedure with no return result (as opposed to an unconstrained result).

foo: func [
    bar [block!]
][
    append bar [a b c]
]

You can still say return ~ or return nothing if you want in such functions if you want to return early.

via @BlackATTR:

"A hole would be something. No, it was...nothing.""

SOMETHING? Test Gives ~true~ for NULL and VOID

While that may sound strange, it fits in with the philosophy.

Hence functions like EQUAL? require their arguments to be [something?]

I'll refer to Carl's arguments about UNSET! is not first class, and asking Is UNSET allowed normally as an argument?"

I think that if you do not specify types for an argument, it should expect SOMETHING?. This is consistent with Rebol2:

rebol2>> foo: func [x] [print type? :x]
rebol2>> foo #[unset]
** Script Error: foo is missing its x argument

And Red:

red>> foo: func [x] [print type? :x]
red>> foo #(unset)
*** Script Error: foo does not allow unset! for its x argument

And R3-Alpha:

>> foo: func [x] [print type? :x]
>> foo #[unset!]
** Script error: foo does not allow unset! for its x argument

(Yes, it's funny to see all three have a different literal notation for UNSET! :roll_eyes: )

So Ren-C will follow suit. You will need to explicitly say your function argument takes ANY-VALUE? in order for it to accept all types including NOTHING.

You can see how Ren-C's terminology works much better. Because historical Redbol has to make a counterpoint to UNSET! which would be NOT-UNSET!. Or SET! or ANY-SET!... but that sort of seems like it might suggest word: and pa/th: as being "any set types". Testing for a non-unset value with set? ties you up in all the reasons I refuse to call the contents of an unset variable "an unset".

Anyway...going forward parameters default to requiring SOMETHING?

1 Like