UPDATE: MODAL PARAMETERS ARE NOW DEAD! ...as far as the core is concerned. It was troubling code that contaminated the model, and it will be troubling no longer.
The elegant solution of isotopic blocks is now solving what they were trying to do.
Regardless, modal parameters were based on an interesting idea: to use literal pattern recognition at the callsite to control turning refinements on and off.
Modal Parameters are an idea to mark an argument conveniently as controlling a refinement--without mentioning that refinement at the callsite, or needing a specialization of the function dispatched through a different name.
Perhaps it's easiest to see by example:
demo: function [@a /mode-a @b /mode-b] [
print ["a:" mold a]
print ["mode-a:" mold mode-a else ["; null"]]
print ["b:" mold b]
print ["mode-b:" mold mode-b else ["; null"]]
]
Using literal (non-quoted) @-arguments will automatically turn on the associated mode refinement. The argument itself will be the appropriate value for the non-@ version of the argument. (WORD! and PATH! will fetch, GROUP! will evaluate, BLOCK! will be unevaluated).
>> demo 1 + 2 10 + 20
a: 3
mode-a: ; null
b: 30
mode-b: ; null
>> demo @(1 + 2) 10 + 20
a: 3
mode-a: #
b: 30
mode-b: ; null
>> foo: "foo" | demo @[x y z] @foo
a: [x y z]
mode-a: #
b: "foo"
mode-b: #
>> foo: [10 @bar] | demo '@[x y z] second foo
a: @[x y z]
mode-a: ; null
b: @bar
mode-b: ; null
The refinements are available to invoke independently as normal. This means that from a specialization or APPLY standpoint the parameter convention would be as-is.
Proof-Of-Concept Implementation In Usermode
Here's a sample of how APPEND might splice blocks by default, but suppress with @.
It was designed to operate on top of the Redbol APPEND/ONLY model where splices are default.
append: function [
series
'nosplice [<skip> the-word! the-path! the-block! the-group!]
value [<...> any-value!]
/only
][
switch type of nosplice [
null [redbol.append series take value] ; no @... act variadic
the-block! [redbol.append/only series as block! splicer]
the-group! [redbol.append/only series do as group! splicer]
the-word! [redbol.append/only series get splicer]
the-path! [redbol.append/only series get splicer]
]
]
Consequences
This leaves splicing the default:
>> append [a b c] [d e]
== [a b c d e]
But if you use an @... at the callsite it offers alternate ways of requesting /ONLY:
>> append [a b c] @[d e]
== [a b c [d e]]
The trickery though is that it has to be a literal @... at the callsite. Indirectly that doesn't apply (if it comes from a reference or expression), it will append in the typical fashion, whatever that would be:
>> item: @[d e]
== @[d e]
>> append [a b c] item
== [a b c d e] ; or should only plain BLOCK! splice?
The callsite permits conventional expressions for the plain case (now an /ONLY behavior), written out as a full evaluation (e.g. the argument is not quoted):
>> append [a b c] reverse copy [d e]
== [a b c e d]
On the other hand, the /only cases are all going through a quoted argument...but these provide variations besides an @-block:
>> append [a b c] @item
== [a b c [d e]]
>> append [a b c] @(reverse copy item)
== [a b c [e d]]
And again, these variations are visible at the callsite; they don't accidentally sneak in to run code as /ONLY if your callsite didn't make it look that way just due to some indirect value:
>> item: @(reverse copy item)
== @(reverse copy item)
>> append [a b c] item
== [a b c reverse copy item] ; ANY-ARRAY! splice?
If you really do want to deliberately append an @... then you can do so with quoting (which you'd have to do for a WORD! or other evaluative type that you didn't mean "do something evaluatory with")