Why Not Allow non-BLOCK! (and non-QUOTED!) Branches?

You might wonder why you're not allowed to just write:

>> if 1 = 1 "hello"
== "hello"

So... we actually tried allowing that for a while. I was the person who advocated for it (with support from @IngoHohmann, @rgchris, and others). My argument was that in Rebol's freewheeling style, you might want to spend your delimiter points on the condition instead of the branch. For example, which of the following two seems to get useful mileage out of the delimiters?

>> if (1 = 1) "hello"
== "hello"

>> if 1 = 1 ["hello"]
== "hello"

Hence we had some experience with what happens when all values were permitted.

Problem: BLOCK! Branches Act Fundamentally Different

Blocks are executed as code. So if you see an expression that isn't a literal used as a branch, you are disoriented. As a reader, you are uncertain whether that expression's evaluation is the end of the evaluation...or if another will happen. And as a writer, you are going to be prone to making mistakes.

This problem is not new, and hits every new user when PRINT treats blocks differently.

>> x: 10
-- lots and lots of code --
>> print x
10

>> x: [format hard drive]
-- lots and lots of code --
>> print x
-- oops --

I've long believed that is a weakness, and a fairly serious one at that. So we should go more toward finding solutions to that category of problem, vs. propagating it more widely and making the system more unpredictable on the whole...for limited value.

But Don't Despair! Ren-C Has "Soft Quoted Branches!"

You may not be able to put just anything in a branch slot, but you can put any quoted thing!

>> if true '<tag>
== <tag>

This flexible approach permits even blocks to be provided literally:

>> either true '[1 + 2] [1 + 2]
== [1 + 2]

>> either false '[1 + 2] [1 + 2]
== 3
1 Like

I found that non-block! branches were a little confusing for me so agree with regression.

2 Likes

I forgot to mention one additional angle, which was actually predicted by Maxim, and that is it's not only CASE that benefits from the structure...but also your branches.

I've really only had the bug happen once. But it was something along the lines of:

 unspaced [
     either condition [
         ...
         lots of code, scrolls off screen
         ...
     ]

    "foo"
]

This happened when an EITHER got effectively changed into an IF, and it wound up consuming the "foo" that wasn't meant for it.

Anyway, I just wanted to bring this up in case anyone needs another reason to get behind the reversion.

I was thinking a bit today how it would be nice to allow literal strings:

print ["RETURNS:" return-note else "(undocumented)"]

But disallow variables, for the reasons given in the thread above:

msg: "(undocumented)"
print ["RETURNS:" return-note else msg]

It's a little bit cleaner than having to use a tick mark, which is hard to see without syntax highlighting unless you use the braced form of string:

print ["RETURNS:" return-note else '"(undocumented)"]
print ["RETURNS:" return-note else '{(undocumented)}]

...but This Makes Legal Branches Different from DO

I've been developing this sort of theory that what branches run are what the core provides for a main DO function...let's say it is called DO*.

I mentioned in a post about efficiency that a QUOTED! should respond in most ways the way that an ACTION! that produces a single value would respond. This gives you an efficient way of passing around a value that can do anything an action does that doesn't require it to have an identity. And one of those things is DO. This ties in to the branching.

That covers the soft-quoted branching behavior case, and makes sense...because it's one of the good reasons we want it for soft-quoted branching. Removing a quote level is computationally trivial and doesn't require any allocations.

But if we were to allow something like a plain TEXT! string to act as a branch, that would be different than what we'd want high-level DO to offer:

>> if true "print {We don't want this.}"
We don't want this.

I think when we add up all the rationales in this thread with that, it makes sense for us to say: there is no action taken on a branch of a conditional that wouldn't match what DO would do for a value of that type.

This gives more hope and clarity to those trying to implement their own branching constructs.

1 Like