Stylistic Questions and Soft-Quoted Branching

Here is a small implementation of SIGN-OF to look at:

sign-of: func [
    "Returns sign of number as 1, 0, or -1 (to use as multiplier)."
    number [any-number! money! time!]
][
    case [
        positive? number [1]
        negative? number [-1]
        default [0]
    ]
]

You could do this with an ELSE if you wished (I've mentioned they are nearly the same, but not quite... a SWITCH/ALL will always run the default, but only run the ELSE if at least one branch runs):

case [
    positive? number [1]
    negative? number [-1]
] else [0]

Moving in another direction: if we accept soft-quoted branching you could write the body as:

case [
    positive? number '1
    negative? number '-1
    default '0
]

It can get even briefer if you understand the premise of fallout (which is why DEFAULT can work here at all). You can omit the default.

case [
    positive? number '1
    negative? number '-1
    '0
]

We're not really set up for performance analysis at this moment. But if we talk about what ultimately will cost the least, that's the cheapest. It's two series, one with 3 cells that will round up to a 4 cell pool (CASE, BLOCK!, terminator)...and one with 8 cells (WORD! WORD! QUOTED! WORD! WORD! QUOTED! QUOTED! terminator). During CASE the evaluator creates basically one frame, which is reused.

By contrast, if you look at the original code at the top of the post with the 3 blocks for the branches, the evaluator does much more work. Each block as a branch sets up a new frame and iteration. This is not to mention the storage--which is more optimal in Ren-C (which can pack single element blocks into a series node vs. needing a dynamic allocation in addition to the series node...because it uses the space that would be tracking information for a dynamic allocation to store the cell itself). But even so, each series node is still the size of two cells...and you need the cell to refer to it...and you're taxing the GC a bit more and losing locality.

The Moral of the Story

I think the moral of the story is that soft-quoted branching should probably be here to stay. It's an unusual idea, and you don't have to use it if you don't feel like it. The biggest backwards compatibility issue on general use is that if you want a branch to be generated from code--or a variable--you have to put it in a GROUP! or somesuch:

 if condition (branch)  ; as opposed to `if condition branch`
 if condition :branch  ; this should probably work too

We could make it so that a single WORD! containing a BLOCK! were used, that it would accept it too. I don't know how wise that is. Certainly accepting an ACTION! would be weird:

 code: ["Hello" print]
 if condition reverse code

If that were allowed, then you'd get the equivalent of:

code: ["Hello" print]
(if condition :reverse) code

e.g. if condition were truthy, it would call REVERSE on the condition...and then evaluate to code. :-/ Anyway, I don't think having to put generated branches in a GROUP! is all that terrible--people are awfully used to putting ordinary branches in BLOCK!s...is it really so oppressive if the rarer case needs delimiters too?

The enhancements to COMPOSE really make this work well, I think:

 compose: [  ; Ren-C won't splice unless you say (( ))
      ...
      data: either condition '(thing1) '(thing2)
      ...
 ]

If you were to try and do that in R3-Alpha, how would you even go about it?

 compose/only/deep: [
      ...
      data: either condition [quote (thing1)] [quote (thing2)]
      ...
 ]

Even in the time when EITHER/ONLY was supported, you couldn't mix and match...both branches would be evaluated or both would be literal. Soft-quoting gives you all options:

 >> either 1 < 2 [print "code!"] '[data]
 code!

 >> either 1 > 2 [print "code!] '[data]
 == [data]

So...while I've been looking at the concept with a critical eye during its inception period, I'm about to take it for granted. If anyone who doesn't like soft-quoted branching (who hasn't drank the Red Groupthink Kool-Aid :roll_eyes:), they should speak up now.

1 Like