Canonizing GROUP! as the Underlying Array Type for Splices

The first concept of representing splices out of isotopes was to make them as iostopic BLOCK!.

You'd get an isotopic block regardless of the input to SPREAD:

>> spread [d e]
== ~[d e]~  ; isotope

>> spread '(d e)
== ~[d e]~  ; isotope

>> spread @[d e]
== ~[d e]~  ; isotope

From the perspective of things like APPEND, it doesn't matter:

>> append [a b c] spread [d e]
== [a b c d e]

>> append [a b c] spread '(d e)
== [a b c d e]

>> append [a b c] spread @[d e]
== [a b c d e]

I Think This Canonization of Splices Is Important

By canonizing splices to just one type, we recover the other types for other meanings that have nothing to do with splicing. That subtlety would be lost if people had to think of every array type as being a splice.

There's no real question in my mind that it needs to be canonized. But which array form should it take?

I Think GROUP! Is A Better Choice

  • It makes the canonization more obvious. Since the input to SPREAD will typically be a BLOCK!, people will learn the type is not preserved quickly:

    >> spread [a b c]
    == ~(a b c)~  ; isotope
    
  • Parentheses look softer and more permeable. They already are "weaker" in that they do not "block" evaluation in the way a BLOCK! does. So their softness makes it feel more reasonable to say that the edges aren't there.

    (This semiotic permeability exists in other places where brackets and parentheses are juxtaposed... for instance in interval notation, where [10, 20) means "the numbers from 10 to 20 without including 20")

  • The nothing state looks kind of like a zero. I've proposed this "nothing" as the non-NULL, non-VOID state that empty branches could coerce to. This has the nice property of signaling the branch was taken, while still being a no-op for things like appending:

    >> if true []
    == ~()~   ; isotope
    
    >> if true [] then [print "Not VOID, so we got the branch ran signal..."]
    Not VOID, so we got the branch ran signal...
    
    >> append [a b c] if true []
    == [a b c]  ; damn, that's cool!
    

Because they aren't void, they overwrite output cells...the information in that cell is lost:

>> 1 + 2 if false [<a>]
== 3

>> 1 + 2 if true []
== ~()~  ; isotope

But I primitives like DECAY and MAYBE offer a trick, that their frame has a cell that gets written with the argument...and they don't have to write their output cell until after they make a decision on their argument. So you can promote one of these "nothing" splices to invisibility that way:

>> 1 + 2 decay if true []
== 3

>> 1 + 2 maybe if true []
== 3