As mentioned previously, MATLAB functions often have several different calling sequences (consisting of different numbers of function parameters) and a variable number of arguments, depending on what the user wants to "catch". The actual mechanism for writing functions which take an arbitrary number of arguments in MATLAB is to define the function to take the special variable varargin. In the example below, we have defined a function called varargin_test(varargin), which takes one (special) argument, varargin, that actually represents any number of real arguments.

varargin provides a convenient way of handling large numbers of independent control flags, not all of which must be specified (i.e. which have sensible default values) each time the function is called. For example, if you have written a function which sometimes plots a line plot and sometimes makes a bar plot depending on the value of some flag which the user passes in, but you don't want to force the user to pass any flags (e.g. a sensible default is the line plot), varargin is a convenient way to handle this scenario. MATLAB's built in functions, like fminsearch handle multiple input arguments in this manner.

In the example below, we assume there are three boolean options which may be set in our script. These are represented by the 'options' array declared at the beginning of the function. Clearly 0 is the default value intended for these options, but any sensible default is allowed. To process the varargin cell array we must always first check to see if the user has passed any arguments at all, hence the check of ~isempty(varargin) (is the varargin cell array not empty?) at the beginning of the function. If this check passes, we then proceed to process all of the arguments using a for loop with an internal case block.


function varargin_test(varargin)
    options = [0 0 0];

    if (~isempty(varargin))
        for c=1:length(varargin)
            switch varargin{c}
                case {'option1'}
                    options(1)=1;

                case {'option2'}
                    options(2)=1;

                case {'option3'}
                    options(3)=1;

            % (continued)

            otherwise         
                error(['Invalid optional argument, ', ...
                    varargin{c}]);
            end % switch
        end % for
    end % if

disp(options);

The case block is used to check for the existence of three option strings. With apologies for the lack of creativity in naming, the options are: 'option1', 'option2', and 'option3', and if any of the three is found in any position (ordering is not important) in varargin, the corresponding entry in the 'options' array is set equal to 1. Finally, at the end of the function we print the current options array to see what effect, if any, our input options have had. Note that if an unexpected option is encountered in the case block, the behavior of the code is to stop immediately and return an error. Depending on your application, it may make more sense to simply ignore unrecognized options and continue processing varargin. Several simple use examples of our function follow, including the result of passing an unrecognized option (an error message).


>> varargin_test
    0 0 0

>> varargin_test('option1');
    1 0 0

>> varargin_test('option1', 'option3');
    1 0 1

    >> varargin_test('option1', 'option3', 'option4');
??? Error using ==> varargin test at 20
Invalid optional argument, option4

We can also use varargin as a means of having named arguments, instead of arguments that are strictly ordered. This is very useful for complex functions that take many optional parameters or debug/verbosity settings. When using this approach, inputs should certainly be checked for correctness by using 'is' functions discussed in the weak typing section, custom functions or conditionals, or a mixture of both. A more recent methodology that incorporates all of these concepts is the inputParser object. However, everything that can be done by the inputParser can be done with varargin and custom checks as well; additionally, the inputParser will require more 'boiler-plate' code. For most functions, the varargin approach shown here will be a good starting point, and can be easily customized to handle more specialized cases.

 
©   Cornell University  |  Center for Advanced Computing  |  Copyright Statement  |  Inclusivity Statement