GET 'FOO instead of :FOO for getting unset variables

When I first learned about the idea that GET-WORD! evaluation allowed you to get an UNSET!, I thought that was kind of cool.

But over time, it began to bother me, because when I'd see a GET-WORD! I didn't really know why it was being used. Was it to avoid invoking a function, or was it to avoid triggering a variable-is-unset error? I'd often get bitten by the case where I was trying to just disarm a function without realizing it was unset all along.

Ren-C's behavior of GET will return NULL if something is not set...allowing you to either work with that (or let it error if where you're passing it doesn't take NULL), or blankify it with try get, or trigger an error on the spot if it's not set with really get. So if you write get foo you're getting the nullable behavior previously possible with just :foo.

This makes me wonder if it would be saner if GET-WORD! errored on unset variables. That way, you could assume seeing :FOO meant you were trying to deactivate an action! so it wouldn't run (or it had some dialected purpose, or was passed to a soft quote, etc.) But it would give people the certainty that the person who wrote :FOO intended for it to be bound and set.

Because historical R3-Alpha, Rebol2, and Red GET all error on unset variables, and GET-WORD! does not, this would be the reverse bias of their behavior.

But I think the GET form reads more naturally when combined with constructs that might operate on NULL. Compare:

x: :foo else [...]
x: get 'foo else [...]

x: try :foo
x: try get 'foo

x: :foo
x: get 'foo

And as mentioned, I've found that many cases of writing things like x: :foo wind up surprised when foo is not set, because they were trying to duplicate an action.

Any objections? The change would obviously be for both GET-PATH! and GET-WORD!

Arguments Against

  1. Unlike other changes, this is one that can't be twisted around to become backwards compatible. There would be no way to be compatible with Red/Rebol2/R3-Alpha's behavior if the evaluator were changed in this way.

  2. Having GET and GET-WORD! finally do the same thing in Ren-C...as they do at the moment...may be seen as a victory for clarity, and hence should be kept.

  3. Casual code that uses GET-WORD! can easily be rewritten to use GET. But some of the functions that need it most are generic, and having to write GET 'X introduces clutter into already tough-to-understand functions. Plus, debugging them after the change is not pleasant.

So if this is to be heeded, then it suggests perhaps SET should be null-tolerant by default as well.

What this may suggest is a need for a cheaper form of a check which ensures something is not null, if you are suspicious it might be.

So when this post was originally written 3 years ago, NULL was synonymous with "unsetness".

Today's NULL is less ornery. It can be retrieved by both word access and by GET.

However, "unsetness" is part of a family of "non-valued" BAD-WORD! isotopes. And GET-WORD! will not fetch them, nor will plain GET.

So GET and GET-WORD! truly are equivalent now. Which is pleasing. And you don't get those accidents from GET-WORD! accidentally tolerating typos when all you meant to do was suppress function application.

In Redbol, this means we get compatibility with Rebol2's behavior for GET-WORD!...but not Red or R3-Alpha. Only some kind of interpreter hook mechanism or command-line switch could override it in the Redbol emulation.

Overall, I'm pleased that ^META words/paths/groups/etc. and the parallel ^META parameters are the only way to deal with bad-word isotopes.