As of July 2022, /ONLY is no longer a refinement available on APPEND, INSERT, CHANGE, FIND, SELECT, COMPOSE, or similar functions. It only appears in the Redbol module through emulation.
"AS-IS" Semantics Are Default
It's easy to empathize with the historical Rebol idea of "splice blocks by default", if you only look at examples where the code is fully literal:
append files [%foo.r %bar.r]
code: compose [... keep [sum: sum + x] ...]
But problems immediately strike when you start using variables that may-or-may-not-be blocks. You can't rely on any invariants, and this leads to broken code:
>> block: [#a {b} [c d e] %f]
>> pick block 3
== [c d e]
>> find block pick block 3
== ~null~ ; anti
Time and experience has proven that "as-is" semantics are the safest and clearest default:
>> append [a b c] [d e]
== [a b c [d e]]
Ren-C offers a new tool for "spliced" semantics...which is to pass a GROUP! antiform ("quoting level -1"). SPREAD is the first function offered which produces them:
>> spread [d e]
== ~(d e)~ ; anti
>> append [a b c] spread [d e]
== [a b c d e]
But there's nothing particularly special about SPREAD, and there will be many other options for defining functions that may-or-may-not return group antiforms...which have more parameterization and nuance.
Making The Value Carry Splicing Intent Brings Systemic Good
The benefits are everywhere, with safer defaults and clear choices...for instance in REPLACE:
>> replace/all [[a b] a b a b] [a b] [c d e]
== [[c d e] a b a b]
>> replace/all [[a b] a b a b] spread [a b] [c d e]
== [[a b] [c d e] [c d e]]
>> replace/all [[a b] a b a b] [a b] spread [c d e]
== [c d e a b a b]
>> replace/all [[a b] a b a b] spread [a b] spread [c d e]
== [[a b] c d e c d e]
Branching code can make decisions to splice-or-not-splice on a case by case basis:
>> code: [<splice> [a b] <no-splice> [c d] <no-splice> 'x]
>> map-each [instruction item] code [
switch instruction [
<splice> [spread item]
<no-splice> [item]
fail ["Bad instruction:" instruction]
]
]
== [a b [c d] 'x]
And COMPOSE can have some slots that splice and others that do not, within the same operation:
>> data: [a b]
>> compose [spliced (spread data) non-spliced (data)]
== [spliced a b non-spliced [a b]]
(COMPOSE is a case where not splicing by default is glaringly obvious as the right choice for a generic operation.)
Antiform Parameter Conventions Should Be Used Sparingly!
Routines that do not intend to react to an antiform should generally not take them as parameters.
As a good example, REDUCE might seem like the kind of thing that could act on group antiforms:
>> append [a b c] reduce spread [1 + 2 3 + 4]
== [a b c 3 7]
But we want to avoid this temptation, to stop the "spread" of antiforms to touching parts of the system that should not be concerned with them. So exercise restraint here...and shift the burden on the calling code to reshape itself so that antiforms only exist at the points that are very close to the calls they affect:
>> append [a b c] spread reduce [1 + 2 3 + 4]
== [a b c 3 7]
Good Riddance /ONLY
The elimination of /ONLY from the semantic model, and to have it not contaminate the user's heads, means that people can learn more generic tools that work in more contexts.
Its appearance in Ren-C will be limited to the Redbol compatibility module.