Variable Number of Arguments

This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production.

The reference material consulted while preparing these pages is listed in the section bibliography.

Written against MATLAB R2026b. The functions below were run in GNU Octave 11.3.0 (the code is valid MATLAB too) and the output shown is Octave’s; error messages differ in MATLAB, so the MATLAB messages and identifiers are quoted from the documentation or marked "not run here". The arguments block with Repeating is not available in Octave and is checked against the R2026b documentation.

A function declares a fixed list of inputs and outputs, but many useful functions do not know in advance how many they will get: plot(x1,y1,x2,y2,...), max(A,[],dim), a solver that takes optional settings. MATLAB offers two special names for this, varargin for inputs and varargout for outputs, and two counters, nargin and nargout. The syntax of a function file is on Functions; the comma-separated lists that make forwarding work are on Comma-Separated Lists.

varargin: a variable number of inputs

If the last name in the input list is varargin, the function accepts any number of additional inputs. MATLAB collects them into a cell array named varargin, one input per cell, so you read them with curly braces: varargin{1}, varargin{2} and so on. varargin may be the only input or come after named inputs:

function r = solve(grid, tol, varargin)

In that case varargin{1} is the third input, and nargin is numel(varargin) + 2. varargin must be last: there is no way to put named inputs after it. If the caller passes no extra inputs, varargin is an empty cell array (0x0), so numel(varargin) and isempty(varargin) are safe tests.

varargout: a variable number of outputs

varargout is the output counterpart. It is a cell array that you fill, one output per cell, and MATLAB hands the cells to the caller in order: varargout{1} is the first output (or the one after the named outputs, if varargout comes after them, as in function [x,y,varargout] = f(a,b), where varargout{1} is the third output and nargout is numel(varargout) + 2). Use nargout to know how many the caller asked for, and fill only those.

nargin and nargout

Inside a function, nargin is the number of inputs the caller supplied and nargout the number of outputs it requested. They are the tool for optional arguments and default values:

  • nargin and nargout (no argument) are the counts for the current call. They are functions, not variables, and are best never used as variable names.

  • nargin(fname) and nargout(fname) return the declared number of inputs or outputs of a function by name or handle, without calling it. For a function that ends its list with varargin (or varargout) the result is negative: the magnitude is the number of declared names including varargin, so -2 means one named input plus varargin. Octave 11.3.0 prints -2 and -1 for the function below; MATLAB documents the same convention (not run here).

function countInputs(a, b, c)
    fprintf("nargin = %d\n", nargin);
    if nargin < 3
        c = 0;
    end
    fprintf("c = %g\n", c);
end
countInputs(1, 2)
countInputs(1, 2, 3)
nargin("countInputs")
nargout("countInputs")

Octave 11.3.0 output:

nargin = 2
c = 0
nargin = 3
c = 3
ans = 3
ans = 0

Calling a function with more inputs than it declares (and no varargin) is an error ("Too many input arguments", not run here), and so is requesting more outputs than it declares ("Too many output arguments"); with varargin and varargout those errors are not raised, so the function must check for itself.

A function with both: narginchk and nargoutchk

narginchk(minArgs, maxArgs) and nargoutchk(minArgs, maxArgs) throw a standard error if the count is outside the range, instead of hand-written if nargin < 1, error(...). Call narginchk first in the function; nargoutchk can be called once you know the outputs. Both take the range as numbers (Inf is allowed as the maximum). The old function nargchk is gone; it returned a message instead of throwing, so code written with it must be rewritten with these two. The MATLAB error identifiers are MATLAB:narginchk:notEnoughInputs, MATLAB:narginchk:tooManyInputs, MATLAB:nargoutchk:notEnoughOutputs and MATLAB:nargoutchk:tooManyOutputs (not run here; Octave prints its own text).

The example is a function that returns the mean of a vector and, if asked, more statistics in the order named by the caller. It uses varargin for the names and varargout for the results:

function varargout = sensorSummary(x, varargin)
%SENSORSUMMARY Mean of x, plus optional extra statistics named in varargin.
    narginchk(1, 4)
    varargout{1} = mean(x);
    for k = 1:numel(varargin)
        switch varargin{k}
            case "max"
                varargout{k+1} = max(x);
            case "min"
                varargout{k+1} = min(x);
            otherwise
                error("heatflow:badStat", "Unknown statistic: %s", varargin{k});
        end
    end
    nargoutchk(0, numel(varargin) + 1)
end
x = [4 8 6];
m = sensorSummary(x)
[m, hi, lo] = sensorSummary(x, "max", "min")
try, sensorSummary(), catch err, disp(err.message), end
try, sensorSummary(x, "median"), catch err, disp(err.identifier), disp(err.message), end
try, [a,b] = sensorSummary(x), catch err, disp(err.message), end
nargin("sensorSummary")
nargout("sensorSummary")

Octave 11.3.0 output:

m = 6
m = 6
hi = 8
lo = 4
narginchk: not enough input arguments
heatflow:badStat
Unknown statistic: median
nargoutchk: Too many output arguments
ans = -2
ans = -1

The first two lines m = 6 are the first call and the first output of the second call. Asking for two outputs without naming a second statistic reaches nargoutchk, which is the point of calling it last. The varargout cells are assigned in order, and a cell that is not assigned for a requested output gives an error in the caller ("One or more output arguments not assigned", not run here), so fill every output you promise.

Forwarding arguments with varargin{:}

varargin{:} expands the cell array into a comma-separated list, which is how a function passes its extra inputs unchanged to another function. The forwarded function applies its own defaults, so the wrapper does not need to know them:

function r = forwardArgs(varargin)
    r = addOffset(varargin{:});
end
function r = addOffset(a, b)
    if nargin < 2, b = 10; end
    r = a + b;
end
forwardArgs(1)
forwardArgs(1, 2)
c = {1, 2};
addOffset(c{:})

Octave 11.3.0 output:

ans = 11
ans = 3
ans = 3

A slice also works: the MathWorks example forwards varargin{1:numPlotInputs} to plot after splitting off an optional trailing title. Forwarding an empty varargin passes no inputs at all, so it is safe. The same idea works for outputs: [varargout{1:nargout}] = other(varargin{:}) forwards both sides, since the left-hand list is a comma-separated list of destinations. When nargout is 0 the list is empty and the call still runs, but then no value is assigned to ans; a wrapper that must print or return the result of a zero-output call should be tested for that case (not run here).

Ignoring inputs and outputs: the tilde

A function that must accept a predefined list of inputs but does not use some of them (a callback receiving src and eventdata) can write a tilde in the position: function btnCallback(h,~). It keeps the unused name out of the function workspace and tells the reader it is unused. Several consecutive tildes are separated by commas (function f(a,~,~)). In a call, [~, i] = max(x) ignores the first output.

When an arguments block is better

varargin hides the contract of a function: the signature says nothing about types, defaults or names. In new code prefer an arguments block (see Argument Validation):

  • optional positional inputs with defaults: tol (1,1) double = 1e-6

  • name-value inputs: opts.Method (1,1) string = "cg", called as f(A, Method="cg")

  • a repeating group: an arguments (Repeating) block declares inputs that may appear any number of times, for example (x,y) pairs. Each name in that block is received as a cell array of all the repetitions, and the block must come after the non-repeating input block. Not run here.

function plotPairs(title, pts)
    arguments
        title (1,1) string
    end
    arguments (Repeating)
        pts (1,2) double
    end
    % pts is a cell array; pts{k} is the k-th [x y] pair
end

This gives size and class checking, tab completion and documentation of the arguments in the Editor, which varargin cannot. Use varargin when the inputs are truly opaque to the function (a pass-through wrapper, as above), when the function is a thin front end for another that does its own validation, or when you must support releases older than R2019b, which introduced arguments blocks. Argument validation cannot be used in nested functions, so a nested function that needs optional inputs keeps varargin.

Pitfalls

  • varargin{1} on an empty varargin is an index error ("Index exceeds the number of array elements", identifier MATLAB:badsubscript, not run here). Test nargin or isempty(varargin) first.

  • varargin(1) versus varargin{1}: parentheses return a 1-by-1 cell, braces return its contents.

  • varargin is last. Named inputs cannot follow it.

  • Counting nargin in a function with named inputs: nargin includes the named inputs, not only the ones in varargin.

  • Forgetting to fill every requested varargout is an error in the caller.

  • Using nargin or nargout as a variable name shadows the function.

  • nargchk is gone; use narginchk and nargoutchk.

  • Name-value options through varargin need manual parsing; an arguments block or inputParser is shorter and checks the names.

Where older books differ

Older books present varargin, varargout, nargin and nargout as the way to write flexible functions and usually test the count with if nargin < 2. That is still valid and still used for forwarding. They predate narginchk and nargoutchk (which replaced nargchk) and the arguments block (R2019b), Repeating arguments and name-value syntax in the call (f(A, Method="cg")), which are the better tool for new code.