UPDATE: This thread is retained for historical purposes, but the issues discussed are now being attacked through various mechanisms... such as quoted branches:
>> if true '[print "hi"] else [print "hi"] == [print "hi"] >> if true '[print "hi"] else [print "hi"] hi
The techniques have grown as the available datatypes have grown, even leading to things like branches that are reduced if they are GET-BLOCK!
>> if true :[1 + 2 10 + 20] == [3 30]
Hence this thread just shows the genesis of the thoughts that pushed from the R3-Alpha status quo into that direction.
An experimental feature that some people have wound up using--while others have not--is that it was possible to use non-blocks in conditional slots. The rationale being that Rebol's desire for expressiveness exceeded its desire for boilerplate.
For instance, in terms of "character economy", you might prefer to see if (x = blah) 3 foo instead of if x = blah [3] foo. This might make it clearer that 3 is not an argument to blah with foo the body, but rather 3 is the desired result. Or you could write x: default [if condition 4] and compact things. It seems the decision to be permissive runs with other core beliefs--including why one does not need to put the condition of IF in a BLOCK! in the first place.
In the early days of open sourcing, Carl was persuaded, and it was committed to GitHub rebol/rebol.
Yet given the fact that blocks would be executed instead of handled as raw values, it seemed a parallel situation to things like APPEND was arising. If you were just writing if condition value, and you didn't realize the variance in behavior between when value was a block vs not...you might be surprised when trying to write generic code...when it worked fine until all of a sudden you used a block. Adding an /ONLY refinement seemed like how APPEND dealt with this, so it seemed to make sense to give generic code authors a similar tool.
Since that time, conditionals like IF have gathered more features. One of them is a protection on the condition against use of literal blocks; any blocks must come from an evaluation in the condition slot:
if [x = 1] [print "you can't write this"]
var: [x = 1]
if var [print "okay, but won't run code--just treat the block as truthy"]
if identity [x = 1] [print "workaround with function that returns its input"]
; ^-- may be useful if you're dealing with code generation
; https://en.wikipedia.org/wiki/Identity_function
Complexity Must Be Balanced Against Benefit
One thing I have come to think is that /ONLY is a hard thing to remember to use if you need it; you don't get an obvious error if you've omitted it. Also, if/only condition [x] is not that much better than if condition [[x]], arguably worse. So the question is whether there's a simpler, more effective, and more helpful way to get the desired help with the if/only condition var case.
The compromise I have in mind is similar to other recent compromises, of a kind of "expert mode" and a "casual/convenient" mode. Casual mode would include a check on branch bodies similar to the one for the condition, except it would only permit evaluated elements if they were blocks. Hence should you ever see if condition var it would check you to make sure var was a BLOCK!, and not some other value. It would still tolerate literals like if condition 3.
The "expert mode" would not have the checks on either the condition or the body, and assume you knew what you were doing.
It might seem this would only affect those who have bothered to try using the feature so far, of which there aren't too many instances. But there's an instance it would change with CASE...you could still write case [false 1 | true 2] but not one: 1 | two: 2 | case [false one | true two], because only blocks would be allowed in evaluative branches unless you used CASE*
. otoh, one: [1] | two: [1 + 1] | case [false one | true two] would be legal.