How ' Became Quoted-Void (and ~ Became Quasi-Void)

Prior to modern quasiforms, ~ was a special "BAD-WORD! with no name", e.g. a null spelling:

>> type of '~
== #[datatype! bad-word!]

>> as text! '~
; null

So unlike regular WORD!, it was possible to have a BAD-WORD! that had no UTF-8 representation. (Yes, this was a sign that something was amiss.)

However, I liked having ~ be something that could be reserved by the system, and I thought the "bad-wordness" plus the lack of any associated text made it a good choice for being what we'd call "none"

>> if none? '~ [print "Yup, that's a none"]
Yup, that's a none.

>> '~  ; console would not show by default

>> mold print "So ~ was the result of things like PRINT"
So ~ was the result of things like PRINT
== "~"

(You can re-read my explanation of why void is a bad return value for things like PRINT or HELP. If you want to communicate to the console that it not print anything, then you need to do that communication through some kind of non-void thing, otherwise that signal is too slippery.)

You could put these BAD-WORD!s in blocks, which made them kind of a lousy choice for the result of a PRINT. So when isotopes came on the scene, it seemed a much better idea to say that none was the isotopic form of something.

So in the first cut of generic isotopes, I said ~ was the quasiform of BLANK! (as opposed to ~_~, which looks pretty bad):

>> quasi _
== ~

>> ~
== ~  ; isotope

>> quasi? '~
== ~true~  ; isotope

>> none? ~
== ~true~  ; isotope

But... Would It Make More Sense Related to Void?

Initially I was at something of a loss for how void fit into the isotopic world.

One of my early reasonings was that VOID was more "etheric" than NULL. So perhaps void was actually the isotopic form of null, and ~ could be null's quasiform:

 >> quasi null
 == ~

 >> ~
 ; void

But this was confusing, since if ~ was the meta of void, there really isn't any such thing as a "~ isotope". You could never make one, because I thought it needed to vaporize.

>> 1 + 2 ~
== 3

I was bothered by taking it for this purpose, because I was pretty attached to ~ for representing unset variables. It looked clean, letting you see the things you've set and haven't:

>> f: make frame! :append

>> f.dup: 2
>> f.value: "a string"

>> f
== make frame! [
    series: ~
    value: "a string"
    part: ~
    dup: 2
    line: ~
]

If ~ represented voids then unset variables would be something like isotopic blanks, and look significantly crappier:

>> f
== make frame! [
    series: ~_~
    value: "a string"
    part: ~_~
    dup: 2
    line: ~_~
]

But it wasn't just in these printouts, also in source. Being able to simply type (x: ~) to unset a variable and have that be the right way to do it...in an object field or just in code, was just too good.

That made me feel pretty attached to the idea that ~ is the contents of an unset variable, which is not displayed by the terminal, and which is ornery to things like ANY or ALL.

1 Like

A post was split to a new topic: The ^META of NULL and VOID

Obviously a lot of things got remapped in the design with isotopes. So I hadn't entered the thinking that it was actually NULL that was isotopic... and VOID was the "more normal" type.

The new conception became that the contents of an unset variable are void isotopes, something that is an ornery form of less than nothing. :fire: :hole: :fire:

This would mean ~ isotope could come back for an ornery value, I called "nihil" for the lack of a better name. Then voids could be meta'd as just a plain apostrophe instead of NULL:

>> meta void
== '

>> meta nihil
== ~

Not only did it look good on the surface, it gave COMPOSE slightly more coherence...because you're allowed to compose in voids, not nulls. So if you've got apostrophes on the outside of a GROUP!, you get the answer you expect:

>> compose ['(void)]
== [']

>> compose ['(null)]
** Error: Can't compose nulls

Not having a meta-form represented via QUASI! suggests voids not being isotopes.

I don't know if this suggests allowing fetching void variables without an error, but... so long as you deliberately assigned a variable to be void... maybe it's... not that bad?

 >> x: if 1 > 2 [print "not run"]

 >> 10 + 20 x
 == 30

I'm not particularly loving that. I feel like you should at least have to say :x there, because part of the argument for "void-in-null-out" being rigorous is that voids are hard to get accidentally.

The decision to make NULL an isotope of the WORD! null (instead of an isotope of--say--BLANK!) is covered in another thread:

~null~ WORD! isotope vs. BLANK! isotope ~_~ meaning null

NIHIL and NONE Became Distinct

What came to be is that NONE is the return result of things like PRINT, and it's an isotopic block indicating a pack of parameters...but it's empty:

>> none
== ~[]~  ; isotope (actually not shown by console)

It's visually noisier than the very succinct ~ isotope...but, since the console doesn't show it, that's not a problem! And it makes a lot of sense to me that if you are trying to do an assignment, e.g. with a SET-WORD! or SET-BLOCK!, that this be considered to not have any values to use for the assignment, and error.

And also, it's nice to be able to unset variables with that single intent:

>> x: ~
== ~  ; isotope

Which is contrary to the intent of blocking assignment, which is part of none's purpose.

YES (I sure hope so!)

2 Likes

:arrow_double_up:

I've streamlined the above thread of historical discussion-with-myself to remove the flip-flopping, and just chronicle the actual points.

This is a curious realization about how an early decision got stuck in my head. NULL was the first thing I implemented that had "no representation", and I gave it the "privileged" state of being the vaporizing result of a quoted nothing:

>> '
; null  (hmmmm...)

As the need to print out a comment there shows, it's not like I'd solved the "has no value representation" problem in some general sense by picking this particular choice. And it turns out to be a pretty bad choice.

It's much better for void. And having the isotopic state represent unset variables is a real joy in terms of the visuals and ergonomics. Being able to say (x: ~) and unset a variable, and have that be the rendering in a list of unset variables draws the attention to the things that are set.

1 Like