Does SET/ANY, GET/ANY-thing matter anymore?


One of the reasons I said I did not like /ANY on GET and SET is because it didn’t seem a good match for OPT-ness. And ANY is a very common construct. So if people get in the habit of naming their refinements /ANY it would be kind of irritating. One doesn’t want to set a bad precedent.

But for reasons that have been reasoned to death, SET-WORD! doesn’t error on null assignments, it just unsets the variable. That’s firm now. No going back on it for Beta/One. Re-read the post if you need to.

It thus seems to make sense that SET of a WORD! would do what a SET-WORD! would do, and not error. And GET returning a null seems okay, since most routines don’t take NULLs as input. If you really want to check something is not null you can do that on the result…e.g. ensure any-value! get word, or the shorter really get word. (Still looking for a better name on that one.)

So there’d seem to be no need for a refinement… except…

…something has to be done about VOID!

VOID! assignments still cause errors on SET-WORD!:

>> x: print "still an error"
** Script Error: x: is VOID!

If you want to write truly generic code (like, say, a READ-EVAL-PRINT-LOOP), you want to really accept not just nulls, but also “ANY”-VALUE!..and that counts void.

So we have a situation where:

  1. This comes up nearly almost never.
  2. “ANY” actually sort of feels like it is sensible for the behavior you’re expanding, since it’s no longer talking about non-ANY-VALUE!d NULLs.

Hence I may be willing to bring GET/ANY and SET/ANY back, but under the new meaning applying to #[void]. Bear in mind: this is materially quite different, as they no longer pertain to “unset” variables. A #[void] is not unset.

But still, get/any 'some-unset-var will answer UNSET? back. Regular GET would have done so too…but what’s the harm?

Question of Nuance: GET on BLOCK! and NULL

Previously this would be an error:

 x: y: null
 get [x y]

There’s no way to put nulls into blocks, so anything you do here besides an error is lying.

But circumstances have come to where I am more laid back about distinguishing NULL and BLANK!. BLANK! really is now genuinely the reified form of NULL–including that they are both falsey. I’ve relaxed the rules on reduce, where it will conflate nulls and blanks rather than error:

>> reduce [if 1 > 2 ["a"] "b" if 3 > 4 ["c"]]
== [_ "b" "c"]

Across the board we are encouraging dialects to think of null and blank as being the same.

So maybe the concept here, would be that if you use regular GET on a BLOCK! your nulls become blanks, but if you do a GET/ANY they become VOID! because you’ve indicated a willingness to understand voids
Putting #[void] in the slots is putting you in the danger zone :guitar: But if voidifying nulls mixes up with actual voids that were already in the values, you were in the zone of danger already.

Doing any better than this would need generalized quoting. Which is probably the direction advanced code would want to go with this. With the proposed tuple-predicates, you could do transformations of the gotten result:

>> x: 1 y: 2
>> get .negative [x y]
== [-1 -2]

>> x: y: null
>> get .quote [x y]
== [' ']

So it seems the /ANY option should just do the convenient thing, and voiding nulls sounds like a fit, since you are effectively saying voids are fine with you.

Afterthought…should plain GET-WORD! not get voids?

If SET-WORD! won’t set voids, it seems that maybe GET-WORD! shouldn’t get them. You really aren’t supposed to be using them as values or signals or anything.

I think I’d be comfortable saying you had to use a special function to get a void out of a variable.