What should do of empty string (`DO ""`) do?

The question of what do [] should return is now basically a done deal... it returns a modern VOID, which is the same value as a conditional that doesn't take it's branch:

>> if true [<a>]
== <a>

>> if false [<a>]
== ~void~  ; anti

>> do []
== ~void~  ; anti

One issue that I mused about was whether there should be parity in DO of an empty string... returning a more vanishable VOID instead of an ornery NULL:

>> do ""
== ~void~  ; anti

On the one hand, being able to accept an empty string at face value as "hey, I meant that empty string" is part of the premise of the whole vocabulary of NULL vs VOID in the first place.

In this school of thought, if you really intended to "opt out of a DO" you would pass it a void, not an empty string, and get a null back.

>> do void
== ~null~  ; isotope

Consider a comparison with something like PRINT:

  • print null and thus print unspaced [void void] are errors
  • print void and thus print maybe unspaced [void void]] is a no-op (returning NULL)
  • print "" prints just a newline, assuming you meant no content for line
  • ...hence so does print unspaced [void "" void] etc.

If you buy into all this, then instead of being paranoid about the historical ways in which empty strings might sneak in, you accept it as meaning what it does and cure the problem at the edges so that everywhere you have an empty string you mean it.

On the other hand, sometimes you are in a situation where strings are the only medium of exchange, and not reacting to the potential problem they represent feels a little wrong. Think for example interfacing with C or JavaScript...

But maybe VOID is the right balance of reaction to this, and do "" returning VOID...instead of being paranoid prickly in some worse way to make NULL, is the coherent behavior of handling what you asked?


I was curious what the JS console in Chrome and Firefox did when you just hit "enter", and found it interesting to see that neither let you; it has no response. You have to at least hit "space". I think that's a bit frustrating in terms of not giving you a way to test the responsiveness. In any case, hitting space gives you the same response as eval("") which is undefined.

You don't get any particular safety from this:

>> x = eval("")
<- undefined

>> if (x) { console.log("doesn't complain on undefineds?"); }
<- undefined

JavaScript does actually consider "undeclareds" as different from "undefineds", where a variable explicitly assigned undefined doesn't error on access (only attempts to dereference). The "undeclared" state might be compared to "unbound".

Anyway, just something to hmm about.

1 Like

Well, seems the worry was for naught, because...

DO Won't Take Strings Without a Rebol [...] Header.

>> do ""
** Error: IMPORT and DO require a header on: <source>

Moreover, DO of a BLOCK! is targeted to not mean "run this block of code in the evaluator".

That will be handled by EVAL/EVALUATE, which won't accept strings.

If you have a string that represents code, and you don't want to combine that code with a header saying how it should be LOAD-ed... you have to TRANSCODE and bind it yourself. Which is now not that hard to do, really... you can run code right where it stands.

outer: 10

string: "outer + inner + arg"

demo: func [arg] [
    let inner: 20
    let code: inside [] (transcode string)
    print ["The result is" eval code]
]

>> demo 30
The result is 60

That might actually be useful. As it is, DO of strings in R3-Alpha was basically useless... unless you were trying to DO a script you got from somewhere else (like, maybe a script stored in a database or something). In which case you will be covered by the DO because you will have the header you need.