What to Call Lone Tilde (~)

So this little guy doesn't have a name:

1896_tilde

Yes it's a "tilde", but if there's a TILDE definition I think it should be talking about the character.

>> print ["name" tilde "me"]
name ~ me

>> char? tilde
== ~true~  ; anti

We're talking about something that evaluates to the antiform of blank (the contents of an unset variable):

>> eval [~]
== ~  ; anti

QUASI-BLANK?

It's an accurate name...

>> quasi _
== ~

But if you're going to be testing for them easily in a block, you want something shorter.

Carl went on a bit of a bizarre track by deciding that #[none] was unweildy in blocks, and he liked zeros better... single characters... so he started using zeros instead of nones, and made ZERO? accept everything.

I started using a lot more zeros in my data structures, especially those that had to be loaded from a file or database, because I knew that zero loaded more efficiently than NONE (no hash was required).

For example, where I would once create REBOL-stored DB records like this:

["name" none none]

I would use:

["name" 0 0]

Because using 0 does not require a hash-and-compare operation (as does the word NONE) nor does it require binding (as does the value NONE)... nor is it the long-form literal #[none], that seems just a bit too cumbersome to my coding style.

You're getting a lot of single-character choices in Ren-C, and which one you use kind of depends on what you want.

QUASI-BLANK is as ornery as it can be while being legal to appear in a block. e.g. if you try to ask it something like EMPTY? you'll get an error:

>> block: ["name" ~ ~]

>> empty? second block
** Script Error: empty? expects [blank! any-series? object! port! bitset! map!]
      for its series argument

If you use BLANK! you have not just a different look, but more routines that are willing to think of it as being some kind of emptiness:

>> block: ["name" _ _]

>> empty? second block
== ~true~  ; anti

There's also #, which is effectively the zero character.

>> block: ["name" # #]

>> append #{DECAFBAD} second block
== #{DECAFBAD00}

>> append "Hello" second block
** Script Error: #{00} bytes illegal in ANY-STRING?, use BINARY!

Does It Need A Name?

Something that makes it desirable for QUASI-BLANK to have a name is that because it's evaluative, you can't just compare to it directly without quoting it.

if '~ = second block [...]

BLANK! and the NUL character don't have that problem.

if _ = second block [...]

if # = second block [...]

But still, Rebol tries to reduce the symboly-ness, and that looks nicer if there's a test you're going to be performing a lot:

if blank? second block [...]

So I think that QUASI-BLANK needs a nice short name, to help avoid people writing sequences like '~ = often in their code.

So I hate to say it, because it would mean shuffling names around again. But maybe the lone tilde that is reified and you can put in a block should take the name TRASH...

>> trash? second ["name" ~ ~]
== ~true~  ; anti

So we wouldn't be able to use trash for the antiform state anymore. :man_facepalming:

I refuse to call the antiform state UNSET!

That I will not budge on.

But What About... NOTHING ?

  • TRASH evaluates to 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

Claude loves it. I love it. DAMMIT. :angry:

I don't think it's a problem that there are three words starting with N here: NULL, NOTHING, and NIHIL. They're distinct, and I think the meanings are quite learnable.

So fine, hell. Here we go with another name change.

I knew I spoke too soon when I said I was settled!

Why? It makes perfect sense to me to define TILDE as ~ and let the character be denoted as "~" (or whatever the syntax is, I forget).

Conceptually, it's better to give it a name for what it represents, vs. what it "looks like".

Tilde is too literal in my book.

Rebol2 called (...) a PAREN! and I disliked that as much as I would have disliked [...] being called BRACK! So I changed it to GROUP!.

TRASH is fitting here.

1 Like

RIEN is recursive name

RIEN A DÉCLARER= Nothing To Declare

Rien
Is
Empty
Nothing

(Edith Piaf approves this name)

Alas, not everyone speaks French…

(Mind you, if PHP can get away with PAAMAYIM_NEKUDOTAYIM, then maybe it’s alright!)

You can certainly call it that. :slight_smile: Not just when you're writing about it in French, but also you can define RIEN and RIEN? in your own personal includes library.

But this brings up an interesting point... which is that NOTHING has to be a function. Because if it were just a value holding an antiform trash you'd get an error by accessing it.

So you will have to use a GET-WORD! when you assign it:

>> rien: :nothing
== ~#[frame! []]~  ; anti 

And it will look like a function if you fetch it with a GET-WORD! and not a plain WORD!.

>> rien? rien
== ~true~  ; anti

>> rien? :rien
== ~false~  ; anti

>> action? :rien
== ~true~  ; anti

It's nice that ~ is symbolic. So return: [~] and such are universal.

But that's where the universality stops. The antiwords ~true~, ~false~, ~null~, ~void~ are hardcoded.

You could tell the console to display them differently, but the symbols for those things are fixed.

I've wondered if there's anything that can be done about that.

It’s an interesting point, certainly. In most languages these are hardcoded into the syntax… but Ren-C is unusual in making them antiforms of specific words. ~true~ etc. aren’t syntax, but literals.

In the past, this has definitely made me feel uneasy: after all, why should five specific words get special treatment, while ~foobar~ etc. remain unused? But I can’t think of any better way to do it.

1 Like

It's probably the endpoint for the medium.

We're starting to reach a point on decisions like this where if this model doesn't work, I won't be the one designing whatever comes next.


"A designer knows he has achieved perfection not when there is nothing left to add, but when there is nothing left to take away." - Antoine de Saint-Exupery

1 Like