Search code examples
rebolred

How to construct a function with a default argument


To make a function with default argument, I tried this:

f: function [a b] [either unset? :b [a + 1] [a + b]]
f 5
f 3 5

then I receive this message *** Script Error: f is missing its b argument.
So, what shall I do?


Solution

  • There's a trick to implement variable-arity functions that some of the built-ins use, most notably help:

    >> ? help
    ...
    ARGUMENTS:
         'word        [any-type!]
    

    Specify your argument as quoted and belonging to any-type! typeset. Or, alternatively, list the allowed types and include unset! in it.

    >> foo: func [a 'b [unset! integer!]][a + do pick [1 b] unset? :b]
    == func [a 'b [unset! integer!]][a + do pick [1 b] unset? :b]
    >> foo 5
    == 6
    >> foo 3 5
    == 8
    

    This, however, comes at a certain price:

    • Optional arguments must come in succession after the mandatory ones.
    • All such function calls within a script now need to be wrapped in parentheses, because otherwise there's no way for the interpreter to guess where your variadic expression ends.
    • You lose the benefits of type-checking, since any-type! accepts any argument; ' in front of the argument also enforces specific semantics, which makes such variadic functions even more cumbersome.
    • Your code becomes unidiomatic: the conventional way to address the need for optional arguments is via refinements. Variadic functions are usually implemented with a single block! argument, which might even be dialected.

    Such an approach is justified only for user-facing polymorphic functions, intended to be used from command-line prompt (such as help) or any other kind of interface that provides clear-cut boundaries for typed expressions (e.g. end of the line, special terminating symbol), and even then the number of optional arguments is kept at minimum.