The not-so-random notes

Matlab: Function Default Arguments

| Comments

Introduction

This is a follow-up article to the one written by Loren. It covers ways to set default arguments of a function in Matlab. The impatient may skip to the last heading while the rest are advised to read top-to-bottom.

The Ugly Way(s)

The following ways to add default arguments to your functions should be avoided:

  • Using the nargin variable in a series of if-then-else or switch statements.
  • Using a struct to carry all the optional arguments. Typically, that struct is checked to have certain fields, which is again equivalent to a series of if-then-else blocks.

The Long Way

Creating an instance of the inputParser class is the heavy artillery of Matlab. It boils down to setting up a few required arguments, a few optional arguments, a few other things and finally calling the parse() method. The details can be found in the documentation or a Matlab-related blog. However, there is a catch: the optional arguments should always have a name! Best explained with an example:

1
function foo(requiredValue, 'optionalValueName', optionalValue)

So, if you are using the inputParser to parse arguments inside foo, then the moment you wish to specify a non-default value for ‘optionalValueName’, you have to write two things: the name itself and the value you want it to have. So the call to foo will look like this:

1
foo(x, 'optValName', z)

The Nice Way

To my mind, the really nice way to add default arguments to a Matlab function was suggested by Loren, one of the most prominent Matlab developers. Here is a slightly modified example from her blog:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function y = somefun2Alt(a,b,varargin)
% Some function that requires 2 inputs and has some optional inputs.

% only want 3 optional inputs at most
numvarargs = length(varargin);
if numvarargs > 3
    error('myfuns:somefun2Alt:TooManyInputs', ...
        'requires at most 3 optional inputs');
end

% set defaults for optional inputs
optargs = {eps 17 @magic};

% now put these defaults into the valuesToUse cell array,
% and overwrite the ones specified in varargin.
optargs(1:numvarargs) = varargin;
% or ...
% [optargs{1:numvarargs}] = varargin{:};

% Place optional args in memorable variable names
[tol, mynum, func] = optargs{:};

And here is Loren’s slightly modified explanation of that code:

First I place the default optional values into a cell array optargs. I then copy the cells from varargin to the correct cells in optargs and I have overridden the defaults. I have only one place where the default values are set, and the code doesn’t grow dramatically in length as I add additional optional inputs. Finally, I spread out the cells from varargin into well-named individual variables, if I want to. Since each element in a cell array is its own MATLAB array, and MATLAB has copy-on-write behavior, I am not creating extra copies of these optional inputs.

So, the code above is just fine if you make the following calls to somefun2Alt:

1
2
3
4
somefun2Alt(a, b)                   % use defaults for tol, mynum and func
somefun2Alt(a, b, tol)              % use defaults for mynum and func
somefun2Alt(a, b, tol, mynum)       % use the default for func
somefun2Alt(a, b, tol, mynum, func) % use no defaults

The Nice Way: Next Move

There still is a problem: you can’t skip a variable. In the example above, you will have to use some value for tol if you wish to have a non-default mynum and you will have to specify both tol and mynum to reach func. So what do you do? Recall the appropriate default values and type them in? Not at all.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function y = somefun2Alt(a,b,varargin)

    numvarargs = length(varargin);
    if numvarargs > 3
        errId = 'somefun2Alt:TooManyInputArguments';
        errMsg = 'a, b, [tol, mynum, func]';
        error(errId, errMsg);
    end

    gaps = cellfun(@isempty, varargin);
    optargs = {eps 17 @magic};
    suboptargs = optargs(1 : numvarargs);

    varargin(gaps) = suboptargs(gaps);
    optargs(1 : numvarargs) = varargin;

    [tol, mynum, func] = optargs{:}

This code uses the convention that an empty value will preserve the default value of the argument. This is actually a common Matlab convention: you may specify [] to say “leave the default argument as it is” practically in any function that has defaults.

Comments