# Nice Way to Set Function Defaults 37

Posted by **Loren Shure**,

Last week, I wrote a post on the `switch` statement in MATLAB. One theme in the comments was about using `switch` (or not!) for setting default values for input arguments that users didn't initialize. I realized that there is a nice
pattern for setting these values that uses some compact, but readable code.

### Contents

### Function Defaults

Sometimes I want to write a function that has some required inputs and some optional trailing arguments. If the arguments
are specified by their order, and not by parameter-value pairs, there is a nice way to accomplish this take advantage of `varargin`. Note that neither of these methods checks the validity of the overridden elements.

Suppose my function requires the first 2 inputs, but there are 3 others that the user can choose to set, or allow them to take default values. In this scenario, once they choose to set an optional input, they must set all the optional ones that precede it in the argument list. Here's an example function header.

dbtype somefun2 1

1 function y = somefun2(a,b,opt1,opt2,opt3)

Here's another way I could write this function header, using `varargin`.

dbtype somefun2Alt 1

1 function y = somefun2Alt(a,b,varargin)

### Setting Default Values

To **set** default values in `somefun2`, I could use a `switch` statement or use `if-elseif` constructs. Here I chose to use a `switch` statement.

`type somefun2`

function y = somefun2(a,b,opt1,opt2,opt3) % Some function with 2 required inputs, 3 optional. % Check number of inputs. if nargin > 5 error('myfuns:somefun2:TooManyInputs', ... 'requires at most 3 optional inputs'); end % Fill in unset optional values. switch nargin case 2 opt1 = eps; opt2 = 17; opt3 = @magic; case 3 opt2 = 17; opt3 = @magic; case 4 opt3 = @magic; end

The code is verbose and, in my opinion, not very pretty. It's also error-prone. If I decide to change a default setting
for one value, I have to update each relevant `case`. What a drag!

Here's a way to set the defaults in one location and then overwrite the ones the user specified.

`type somefun2Alt`

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{:};

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 (see this post for more information).

### Other Methods for Dealing with Optional Inputs

There are other methods for dealing with optional inputs. These include specifying parameter-value pairs. With or without
such pairs, you can use `inputParser` to help set the values you use. You can specify the optional input in a `struct`, with fields containing the various options, and you can use cell arrays, but then you have to decide how to structure and
specify the contents.

### Your Techniques for Specifying Optional Values

Do you have a technique for specifying optional values that works well for you? Please share with us here.

Get the MATLAB code

Published with MATLAB® 7.8

**Category:**- Best Practice,
- Cell Arrays,
- Defaults

### Note

Comments are closed.

## 37 CommentsOldest to Newest

**1**of 37

**2**of 37

**3**of 37

**4**of 37

function myfcn(a,b,tol,mynum,func) if ~exist('tol','var'), tol = eps; end if ~exist('mynum', 'var'), mynum = 17; end ...With varargin and nargin, I have to change multiple lines to add a new optional parameter or change the order of parameters. It also becomes tricky to allow uses like myfcn(100, 200, eps, [], @rand) where the [] means that the function should assign the default value for mynum. With the EXIST test, it becomes straightforward:

if ~exist('mynum','var') || isempty(mynum), mynum = 17; end

**5**of 37

**6**of 37

**7**of 37

**8**of 37

**9**of 37

**10**of 37

**11**of 37

**12**of 37

```
function varargout = tsp_ga(xy,dmat,pop_size,num_iter,show_prog,show_res)
% Process Inputs and Initialize Defaults
nargs = 6;
for k = nargin:nargs-1
switch k
case 0
xy = 10*rand(50,2);
case 1
N = size(xy,1);
a = meshgrid(1:N);
dmat = reshape(sqrt(sum((xy(a,:)-xy(a',:)).^2,2)),N,N);
case 2
pop_size = 100;
case 3
num_iter = 1e4;
case 4
show_prog = 1;
case 5
show_res = 1;
otherwise
end
end
```

I'm not sure how I could make your method work in the case of the distance matrix (dmat) input, because it's size depends on the number of xy points. In other words, I don't have a way to set the default for the second input without knowing what the first input is. **13**of 37

**14**of 37

%% Process optional arguments function paramsStruct = processArgs(varargin) % Get the properties in either direct or P-V format [parent, pvPairs] = parseparams(varargin); % Now process the optional P-V params try % Initialize with default values paramName = []; paramsStruct.dividercolor = ''; paramsStruct.dividersize = 5; % other default params can be specified here supportedArgs = {'orientation','parent','tooltip',... 'dividerwidth','dividercolor','dividerlocation',... 'dividerminlocation','dividermaxlocation'}; while ~isempty(pvPairs) % Ensure basic format is valid paramName = ''; if ~ischar(pvPairs{1}) error('invalidProperty','Invalid property'); elseif length(pvPairs) == 1 error('noPropertyValue',['No value specified for property ''' pvPairs{1} '''']); end % Process parameter values paramName = pvPairs{1}; paramValue = pvPairs{2}; %paramsStruct.(lower(paramName)) = paramValue; % good on Matlab7, no good on Matlab6... paramsStruct = setfield(paramsStruct, lower(paramName), paramValue); %#ok Matlab6 pvPairs(1:2) = []; if ~any(strcmpi(paramName,supportedArgs)) url = ['matlab:help ' mfilename]; urlStr = getHtmlText(['<a href="' url '" rel="nofollow">' strrep(url,'matlab:','') '</a>']); error('invalidProperty',... ['Unsupported property - type "' urlStr ... '" for a list of supported properties']); end end % loop pvPairs catch if ~isempty(paramName) paramName = [' ''' paramName '''']; end error('invalidProperty',['Error setting uisplitpane property' paramName ':' char(10) lasterr]); end endIn the code body, I simply check or use the value of paramsStruct.ParameterName. So simple. Note: the code uses Matlab's built-in parseparams function to separate the PV argument pairs. This step can easily be done without resorting to parseparams, which is simply a convenience function.

**15**of 37

function my_func(varargin) parser = my_custom_input_parser(); % Format: % parser.add_param_value_with_default(... % param_name ... % default, ... % test_function, ... % ‘One line help’, ... % ‘Multiline help’.'); parser.add_param_value_with_default(... ‘param1’, ... [1 2 3], ... @isnumeric, ... ‘One line help’, ... ‘Multiline help’.'); % Check if help should be displayed ('help' is the input) and exit if so. if parser.display_help_if_req(varargin{:}); return; end p = parser.parse(varargin{:}); % p is a struct endThis allows default setting, testing of values, and easy (but non-standard) help mechanism. I like the inputparser approach of supporting either PV pairs or a struct + PV pairs. I also have a fairly simple method of the custom input parser to generate an html help page of the input arguments. As more of my code is moving towards object-oriented classes I have adapted this procedure for class properties. In order to do this I generate a “parameters” class and use inheritance to bring these properties into my class. I know that Matlab can use dynamic properties but I have found these to be quite slow for get/set access. By “generate” I mean that the parameters class code is automatically generated (ie I only need to write the template) using part of the help for the class (which makes it very easy for other members of my team to use the same procedure for their classes). For example, the “functional” class would be something like:

classdef my_class < my_class_params %MY_CLASS is a class with the following parameters. % % Parameters: % param1 = One line help for param1 % Multiline help. % Default = [1 2 3] % Basic test = @isnumeric % % param2 = One line help for param2 % Multiline help. % Default = [1 2 3] % Basic test = @isnumeric % % See also MY_CLASS_PARAMS. methods (Access = public) function this = my_class(varargin) % Varargin can contain PV pairs, a struct + PV pairs, or a my_class_params object + PV pairs. this = this@ my_class_params(varargin{:}); end end endAll the defaults, help, basic checks are now very visible in “my_class” and accessible to the normal help/doc functions or the html page version. If anything changes for these (or at startup) I rerun the function I have that parses these files and generates the my_class_params.m file using a template (via the excellent m2html package). One additional advantage of the class generation is that I can add “compile-time” options. For example I have 2 templates, one that includes all the parameter checking in the my_class_params, and one that does not (and is faster). It’s like an “assertions on/off” debug flag that Matlab unfortunately does not have. Not simple to say the least, but it’s quite effective.

**16**of 37

` ````
function y = somefun2(a,b,tol,mynum,func)
% Some function with 2 required inputs, 3 optional.
% Check number of inputs.
if nargin > 5
error('myfuns:somefun2:TooManyInputs', ...
'requires at most 3 optional inputs');
end
defaults = {eps, 17, @magic}; % Store defaults, change them here only.
% Fill in unset optional values.
switch nargin
case 2
[tol mynum func] = defaults{:};
case 3
[mynum func] = defaults{2:3}
case 4
func = defaults{3};
end
```

I think I like this better when there are only a few optional arguments. As the number of optional arguments gets larger, the function declaration line becomes too ugly for me. In this case I think I would go with using varargin.
Great article! Thanks. **17**of 37

**18**of 37

**19**of 37

**20**of 37

` ````
function somefcn(reqArg1,reqArg2,varargin)
% Usual checks for number of arguments...
% Beautifully, being a cell array, optArgs can accommodate structures (to pass options to an optimization solver, for example), function handles (to choose a particular optimization solver, for example) etc.
optArgs = {1,2,3};
nullArgs = findnull(varargin);
[optArgs{~nullArgs}] = varargin{~nullArgs};
% ...
function ind = findnull(a)
a = a(:);
len_a = length(a);
ind = false(len_a,1);
for ctr = 1:len_a
if isequal(a{ctr},[]), ind(ctr) = true; end
end
```

**21**of 37

**22**of 37

```
>> c = mat2cell(1:1e6,1,repmat(1,1,1e6));
>> tic, d=cellfun('isempty',c); toc
Elapsed time is 0.115583 seconds.
>> tic, d=cellfun(@isempty,c); toc
Elapsed time is 7.493989 seconds.
```

Now, the obvious solution would be for the internal Matlab code to check for function-handle equality and use the optimized version if possible. Perhaps a future Matlab release will do this. Hint hint MTW? :-)
Yair Altman **23**of 37

**24**of 37

**25**of 37

**26**of 37

**27**of 37

**28**of 37

**29**of 37

function outdata=movavg(indata,varargin) %Smooths indata with a boxcar windowed moving average p=inputParser; p.addRequired('indata',@isnumeric); p.addParamValue('wind_size',[],@isnumeric); p.parse(indata,varargin{:}); if isempty(p.Results.wind_size) wind_size=round(length(indata)/20); else wind_size=p.Results.wind_size; end if wind_size<1, wind_size=1; end n_outdata=length(indata)-wind_size+1; outdata=zeros(1,n_outdata); for a=1:n_outdata, outdata(a)=mean(indata(a:a+wind_size-1)); end

**30**of 37

**31**of 37

p_res = p.Results;Now you have a simple structure 'p_res' that can be modified as usual. Maybe this works for you. - Nio

**32**of 37

optargs(1:numvarargs) = varargin;from your previous function somefun2 I saw that

switch nargin case 2 opt1 = eps; opt2 = 17; opt3 = @magic; case 3 opt2 = 17; opt3 = @magic; case 4 opt3 = @magic; endIt seems that func is the argument if you only add one argument in the input and you put the argument func at last. So I think it should be

optargs(3-numvarargs+1:end) = varargin;Or, the argument should be in reverse order

[func, mynum, tol] = optargs{:};-Zhenyu

**33**of 37

**34**of 37

function foobar(varargin) Defaults = {A,B,C...}; Defaults(1:nargin) = varargin;- Two lines of short and readable code. - Works with any data types or functions. - Does not unnecessarily increase the cyclomatic (McCabe) complexity value. - Is much much quicker than calling 'exist', 'isempty' or the like. - Assigning, reassigning or using values requires careful attention to order. Be careful! - The number of input arguments can also be more than the number of default values. The cell array 'Defaults' will have at least as many cells as there are input variables, but will contain no less than those that are defined as function defaults. Very useful, on occasion where a minimum number of defaults need to be set. - Empty values may be replaced with defaults using:

function foobar(varargin) Defaults = {A,B,C...}; Inds = find(cellfun(@isempty,varargin)); varargin{Inds} = Defaults{Inds}; Defaults(1:nargin) = varargin;but this is slower, due to the 'find' and 'cellfun', and no longer allows more input arguments than defaults (unless it is possible to guarantee that they are not empty). All in all, a very neat way of setting function default values using current MATLAB syntax.

**35**of 37

**36**of 37

**37**of 37

## Recent Comments