If you had a function that took a literal argument in Rebol2, it could be "endable"... if it accepted UNSET! as an argument.
This feature was added primarily for HELP, so that you could say either:
>> help
...GENERIC HELP usage information...
>> help topic
... HELP for specific TOPIC...
It was a very limited form of variadic-ness...generally used only in console-oriented commands (HELP, LS).
You couldn't use it with a function that was evaluative. Hence this wasn't possible:
redbol>> printer 1 + 2
3
redbol>> printer
You called the PRINTER function with no arguments
; ^-- not possible to accomplish with an otherwise evaluative argument!
So handling missing arguments was tied to taking the argument literally.
It was also ambiguous. The signal for literal parameters that were endable-and-missing was to make the parameter accept UNSET!. Which meant they couldn't tell the difference between help #[unset!]
and just-plain-help
:
red>> help #[unset!]
To use HELP, supply a word or value as its
argument:
help insert
help system
help system/script
...
Ren-C Can Resolve the Ambiguity for Literal Arguments
Because antiforms can't occur in "source" code, a function taking a literal argument could receive an antiform as an unambiguous signal that the end was reached.
Any antiform could serve as that signal (and different options have been tried). But for the moment let's say it was the antiform of the word ~end~
:
>> help ~end~
~end~ is a quasiform word! ; received the quasiform of END
>> help
To use HELP, supply a word or value... ; received the antiform of END
Normal Evaluative Arguments are Still Ambiguous
When a quasiform evaluates, it produces an antiform. So we still would have ambiguity if we tried to use the ~end~ antiform:
>> printer 1 + 2
Received 3
>> printer
Received the antiform of ~end~
>> printer ~end~
Received the antiform of ~end~
But ^META Arguments Can Be Unambiguous
Meta-arguments are evaluative, but if the evaluated value is not an antiform, it will just have a quote level added. Antiforms will be passed as the quasiform. This means you can never "legitimately" receive an antiform as an argument to a ^META function.
>> meta-printer 1 + 2
Received '3
>> meta-printer first ['3]
Received ''3
>> meta-printer ~end~
Received the quasiform of ~end~
>> meta-printer first [~end~]
Received '~end~
So a special rule could be invoked that endable ^META arguments give an antiform to signal the missing parameter:
>> meta-printer
Received the antiform of ~end~
Should Only Literal / ^META Arguments Permit Endability?
The ambiguity for "normal" evaluative arguments only arises if your type checking would allow the antiform. If your function only accepts INTEGER! (for instance) then the antiform of ~end~ isn't "in-band", and it may be more convenient for you to not worry about the ^META convention.
int-printer: func [arg [<end> integer!]] [
either arg = ~end~ [
print "Received end antiform"
][
print ["Received integer:" arg]
]
]
That seems okay to me.
The system could try to stop you from shooting yourself in the foot... so that if you marked a normal parameter as <end>
it would try to type check an ~end~ antiform against your parameters:
>> anti-printer: func [arg [<end> antiform?]] [...]
** Error: typespec [<end> antiform?] ambiguous for ~end~ antiform
So is that annoying, or helpful?