The fallout from the SWITCH fallout feature

To try and be a little bit more clever, Ren-C added the ability of SWITCH to let the last value "fall out". So instead of writing:

rebol2>> result: switch/default "z" [
            "a" [print "won't run" 10]
            "b" [print "this either" 20]
         ][
            30
         ]
== 30

You could just write:

>> result: switch "z" [
       "a" [print "won't run", 10]
       "b" [print "this either", 20]
       30
   ]
== 30

Additionally, because Ren-C's switch cases evaluate, you could put arbitrary code and it will fall out:

>> var: "a"
>> result: switch "z" [
       var [print "won't run", 10]
       (first ["b" "c"]) [print "this either", 20]
       10 + 20
   ]
== 30

It was an interesting idea of folding the default inside the same block as the clauses. It that felt a bit like being able to fold defaults inside a CASE statement using TRUE:

>> case [
      1 > 2 [<nope>]
      3 > 4 [<nope>]
      true [<your default here>]
]
== <your default here>

But with ELSE and THEN, is this feature still interesting?

 result: switch "z" [
     "a" [print "won't run" | 10]
     "b" [print "this either" | 20]
 ] else [
     10 + 20
 ]

The fallout feature doesn't have much cost; it's nearly free. And for the performance-minded, it's the fastest way to have a default value.

Does fallout make SWITCH feel like it's fancier and has good dialecting bones, taking advantage of Rebol's unconventional-ness? Or does it make SWITCH seem weird...like you're looking at incomplete code, missing the branch for the last switch case? What do people think looking over it in the above examples?

1 Like

I should add that I'm seriously considering getting rid of SWITCH/DEFAULT. With void as the generic signal for "this action was a no-op", there's a much richer landscape of ways to deal with defaulting that apply to every operation that obeys the conventions.

More useful IMO would be to add SWITCH/ALL. With the ability to do soft-quoted evaluations, there are actually meaningful use cases for switch/all x [...] also [...] else [...]

This would be a change to the core C native--obviously a SWITCH which supported /DEFAULT could be grafted on top of that.

Update June 2018: SWITCH/DEFAULT eliminated

Update September 2019: /DEFAULT can be added back to a derivation of SWITCH for compatibility via AUGMENT

Removing /default makes sense given the availability of else. I'll add my vote to make this change.
All of these small changes reduce the size of the language hence make it easier to learn.
Good stuff. -John

1 Like

I'm going to come out in favor of the switch fallout feature. Reasons:

  1. Performance-wise, it is the fastest defaulting mechanism...faster than ELSE or SWITCH/DEFAULT.

  2. If people don't like it, they don't have to use it.

  3. Due to the nature of ELSE, it completes the left hand side of an expression. Sometimes when an expression can be completed you don't want it to...and this means you need <-, so for instance you have to write append x <- switch [...] else [code]. But with switch fallout, you can do it as append x switch [... (code)].

Point 3 is a reason to not blindly convert EITHERs into IF...ELSE. Or CASEs ending in true [...] to CASE...ELSE. Sometimes it's better to duck an arrow.

I've also noticed that CASE ending in true [...] can be more compact than a CASE...ELSE. That applies to the fallout switch too, it's just shorter.

(Note: As some have pointed out, writing /else [...] as your last "truthy" case is actually faster, because there's no variable lookup involved (true => #[true]), /ELSE is just "truthy" by nature. So we should probably prefer that as an idiom.)

Now a new question...

Should CASE also support fallout?

There've been some increases to the strictness of CASE. It now pretty much requires blocks for the clauses, and given that it does that, might we allow:

>> case [
       1 > 2 [...]
       3 > 4 [...]
       10 + 20
   ]
== 30

It would be consistent with SWITCH, and the risks of such a construct are much lower than they used to be. Note that since there's strict alternation, you couldn't say 10 + 20 30, it would measure that exactly one expression ran and then it either ends or there's a source-level block.

A lot of the same arguments for why it's good for SWITCH apply here, too. (And of course, useful for Code Golf...) Certainly the "you don't have to use it if you don't want to" seems a pretty strong point.

Update: Fallout from CASE committed

1 Like