We've had considerable time now to mess around with the option of letting IF take non-block branches.
As the person who advocated for it initially, I can say that I've been deeply on the fence about it...increasingly so, now to the point of thinking we should revert it.
The conundrum we wound up with is that BLOCK! branches are treated fundamentally differently from other kinds of values...they 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 --
But 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.
I've added in some wild protections, to try and only let you use unevaluated non-block literals as branches. I think it's cool that "evaluated bit" mechanism has been developed, and it is a useful tool. But in my own experience, this has created a hassle when writing one's own custom conditionals that are layered on top of Rebol's conditionals.
(e.g. the user has passed you something that it wants to act as a branch, same as other Rebol constructs. You want to treat that branch as a black box, but it complains when you say
(if modified-condition :branch) when branch is not a block, because although the user called you with a literal, you're now passing it through via a GET-WORD! evaluation...)
I know @IngoHohmann has spoken up for non-block branches, and @rgchris has too. Yet I'm afraid I'm going to recommend we abandon non-block branches, because they cause too much trouble for what they have truly gained us. Instead, I will suggest people use
!! if they want to avoid blocks and get literals... you are even allowed to do evaluations on those branches...as long as you don't mind the fact that they run regardless of whether the condition takes (note that this was an issue in non-block branches as well: either c x y would do a word-fetch of both x and y, even if it wound up not using what was fetched). :-/ Point being condition ?? 1 + 2 is legal, albeit wasteful by performing an addition if the condition turns out to be false.
Update: There's now even a
?! which is like an infix UNLESS that doesn't execute branches, where
x ?! y acts as
(not x) ?? y.
I will also recommend CASE be changed to disallow non-block branches:
block: [print "this will be legal, too"] x: 17 case/all [ 1 > 0 [print "this will be legal"] 2 > 0 block 3 > 0 x ;-- not legal ]
Instead, one can use the CHOOSE primitive, which will never double-evaluate, and returns blocks as-is:
x: choose [ 1 < 2 [print "returned as value"] ] >> x [print "returned as value"]