2010-07-22

Default Parameters

Subroutine calls can be simplified when one doesn't have to provide arguments for every parameter.

Specifying defaults in the signature

If you're lucky, your language might allow your signature to specify defaults:

function f(x = 3, y = 5, z = 10) {
    ...
}

f();            // same as f(3, 5, 10);
f(44);          // same as f(44, 5, 10);
f(32, 1);       // same as f(32, 1, 10);
f(17, 15, 22);  

Other forms for specifying defaults:

(DEFUN f ((x 3) (y 5) (z 10)) ...)
def f(x := 3, y := 5, z := 10) ... end

Supplying defaults in the subroutine body

Some languages don't support a syntax in which defaults can be supplied in a signature, but they do let calls be made with fewer arguments than parameters. Parameters for missing arguments automatically receive a default value like nil or undefined. Whatever the value, these languages almost always treat it as falsy, allowing the use of an ||= assignment, as in:

function f(x, y, z) {
    x ||= 3;
    y ||= 5;
    z ||= 10;
    ...
}

The problem here is that other values which you might want to pass in might be treated as falsy by a language (such as 0 or the empty string), so this approach will not work in general. The idea can be implemented if the language has an operator to determine whether a value is "defined":

function f(x, y, z) {
    x = defined x ? x : 3;
    y = defined y ? y : 5;
    z = defined z ? z : 10;
    ...
}
function f(x, y, z) {
    x = 3 if not defined x;
    y = 5 if not defined x;
    z = 10 if not defined x;
    ...
}
function f(x, y, z) {
    if (!defined(x)) {
        x = 3;
    }
    if (!defined(y)) {
        y = 5;
    }
    if (!defined(z)) {
        z = 10;
    }
    ...
}

These forms aren't as pretty because of the logic required in the body as opposed to the signature.

Overloading

Some languages allow neither defaults to be specified nor calls with too few arguments. In this case you can simulate defaults with overloading. In Java:

public void f(int x, int y, int z) {...}
public void f(int x, int y) {f(x, y, 10);}
public void f(int x) {f(x, 5, 10);}
public void f() {f(3, 5, 10);}

No comments:

Post a Comment