(For those culturally unaware of the reference: DoubleMint gum commercials)
Doubled-up blocks are distinct to the evaluator from single ones. if true [[stuff]] acts different from if true [stuff].
This is not the case for doubled-up groups. ((1 + 2)) will act the same as (1 + 2)…because if you’ve got a single group inside of a group, there’s nothing for it to interact with.
So rather than let them sit around being useless, why not use these cool-looking things for some practical purposes? Here are two nifty new uses…
Double Groups in COMPOSE mean /ONLY for that insertion
>> data [a b c] >> compose [plain: (data) only: ((data))] == [plain: a b c only: [a b c]]
Boom. The bulkier look alludes to the insertion being “heavier” and more isolated.
For the cost-conscious, it might look like you’ve got an extra series now. But Ren-C has some hard-core efficiency tricks that make such doublings very efficient, through what is called the “small series optimization”. And you got rid of the COMPOSE/ONLY 2-element path…which at 2 elements long it doesn’t qualify for the small series optimization. Plus refinement processing costs more in the evaluator than dispatching through a plain word.
It’s not just more convenient and compact, but more efficient.
Double Groups in PARSE mean “execute and splice as rule”
There’s efficiency to be gained when you compose your parse rules ahead of time. But what if the rule depends on other things, and you want to generate a rule to splice in that gets composed in every time it’s run?
>> num: 1 >> char: #"a" >> did parse ["a" "bb" "ccc"] [ some [ into [(( rule: reduce [num char] num: num + 1 char: char + 1 rule ))] ] end ] == #[true]
(Note: You shouldn’t need the block outside the doubled group for the INTO, but at the moment INTO isn’t aware of these doubled groups in its immediate argument…so they have to go in a block rule. It will be updated to recognize them directly.)
If the expression inside the double group evaluates to a null, it splices nothing into the rule stream. With so many null-signaling routines to choose from, that’s rather cool.
>> did parse "aaabbbcccddd" [ some "a" ((case [1 > 2 [[some "x"]] 4 > 3 [[some "b"]]])) some "c" ((switch 1 + 2 [ 4 [[some "z"]] 3 + 2 [[some "q"]] ])) some "d" end ] == #[true]
Though you can return BLOCK! rules to splice, you can also just return single WORD!s. At the moment, returning a BAR! is disabled, though that might be relaxed based on feedback.
The fact that the blocks are not spliced is conveyed nicely in parity with the /ONLY-ness character of doubles in COMPOSE.
Pretty neat, huh?
There are some other cool compose features forthcoming that aren’t ready yet, but this kicks it off with a very usable thing you can get started with right now. It seems to me that nearly every COMPOSE/ONLY I’ve seen is better off with the doubled groups, as only some things need the /ONLY and it helps call out the ones that do.