What should enfix IF-NOT and blank-testing ELSE be named?


#1

Given that this works:

print ["you are" (is-rebol-user then ["very"]) "cool"]

One may wonder why this doesn’t work:

print ["one is" (1 > 2 else ["not"]) "greater than two"]

Although the more frequent question is why this doesn’t work:

x: all [...] else [1 + 2]

While neither work, they are two different desires. The “print” case wants ELSE to return void if a logical test from the left is false, and run the branch otherwise. The “all” case wants ELSE to return the result of the ALL if it’s truthy, but the result of running the branch if it’s blank.

Both are useful ideas… but neither of those ideas are today’s ELSE. This is because ELSE is meant to be used in conjunction with some kind of conditional branch. It tests its left hand side for voidness, not for falsey-ness.

This is important. If it didn’t work that way, you couldn’t write:

frob-mode: if detect-flag flags #disable-frob [
    false
] else [
    true
]

ELSE’s mechanic is to look at the evaluation on its left…and decide if will evaluate to that as its result, or the result of evaluating its own branch. Here we clearly want it to consider FALSE an established and decided-on value by the prior branch, it shouldn’t run its own code. And I’d argue that had the first branch been BLANK!..a fully legitimate value for putting in a block…it should also accept that…probably. (Premise questioned below.)

Hence void is the only signal from the left it uses to trigger running its branch. And my feeling has been that it’s more important than the other cases… given you could have written:

print ["one is" (1 =< 2 then ["not"]) "greater than two"]

…or…

x: any [all [...] 1 + 2]

I’ll also say that having ELSE not be designed for those purposes is not that unusual. I don’t think there are many languages which have the independent use of ELSE branches without some conditional clause of what to do in the true case. Not all languages have THENs…C doesn’t, nor does its preprocessor. But you can’t just throw an ELSE in without a true-branch somewhere.

But let’s look at the two cases in more detail.

enfix IF-NOT

The first one is just an enfix variation of IF-NOT:

>> enfixed-if-not: enfix :if-not

>> print ["one is" (1 > 2 enfixed-if-not ["not"]) "greater than two"]
one is not greater than two

Easy to code…but hard to name. It’s the anti-THEN. You’ve just stated a falsehood of some kind, and now want to hang a branch on it. Were it Wayne’s World we could call it THEN…NOT!

Analogy question: IF is to THEN, as IF-NOT is to … ? Bear in mind the arguments above of why it can’t be ELSE.

Strange suggestion: NAY? It’s not completely terrible, so maybe a good first try. @IngoHohmann voted it up

>> print ["one is" (1 > 2 nay ["not"]) "greater than two"]

enfix EITHER-TEST-SOMETHING?

Depending on whether you want it to override FALSE and error on void or not, this is either checking for “truthy?” (now DID) or SOMETHING? (e.g. not blank or void). Let’s go with the latter, and I’ll explain why in a second.

>> either-test-something-enfixed: enfix specialize 'either-test [
    test: :something?
]

>> x: all [false true] either-test-something-enfixed [1 + 2]
== 3

>> x: all [true 7] either-test-something-enfixed [1 + 2]
== 7

Don’t tell me you’re not impressed. :slight_smile:

One “radical” possibility that was once considered was that taken branches not be allowed to return void or BLANK!, and that ELSE consider blank another provocation to run (along with the traditional void). That would solve some problems, yet disrupt the intent of:

x: if 1 < 2 [
    _
] else [
    <nonblank>
]

You’d get something else back from that besides blank. While #[false] would be a possibility that might “gloss over” the fact that you couldn’t get a blank (by giving you something that was still conditionally false), I think that cover-up probably does more harm than good…and BAR! would be a more “jarring” choice to inform you that you needed to do something else to get what you intend.

So this would mean deliberately returning blanks would require using the /ONLY version IF/ONLY (IF*), used today only if you really want a void…and you couldn’t combine that with ELSE, though possibly ELSE* might be written to trigger only on voids as well as delivering its result verbatim. :-/ Given that DEFAULT considers blank as much a non-value as a void by default, this might well be the smartest option.

Anyone against it? I feel like on balance, this might be the thing to do…because people are going to want to do all […] else […], and confused if it doesn’t work.

UPDATE: I tried this and decided the better strategy and the better name for this is to use the short-circuit OR that we already have…which is thus kind-of-sorta-like an “EITHER-TEST-TRUTHY”…testing the left side for logical truth. It only needed slight modification so that if its input values stay in the LOGIC! domain it will return a LOGIC!, but otherwise it will act like ANY [] and return a BLANK! on failure or the last value evaluated. While this is not perfect, trying to make ELSE “serve two masters” created too much complexity…so it had to be cut out.

The solution to be trying now is here:

https://github.com/metaeducation/ren-c/commit/c0eecb654a69203a633e2b830aecb975cbe222f8


Tapping The Untapped Potential of Short Words