Polyglot
Languages MATLAB functions
MATLAB § functions

Functions and scripts

A function in MATLAB is a .m file (or a portion of one) that begins with the function keyword and that, when called, executes in an isolated workspace. Functions are the principal mechanism for reusable computation; scripts and the REPL are the principal mechanism for interactive exploration. The file-level model — one principal function per file, named after the file, optionally followed by local helpers — has been the language’s organising convention for forty years.

The function file

% File: trapezoid.m
function y = trapezoid(f, a, b, n)
% TRAPEZOID  Approximate the integral of f from a to b using n trapezoids.
%   Y = TRAPEZOID(F, A, B, N) returns the trapezoidal-rule approximation
%   of the integral of the function handle F over [A, B] with N intervals.
    h = (b - a) / n;
    x = linspace(a, b, n + 1);
    y = h * (sum(f(x)) - (f(a) + f(b)) / 2);
end

The first line function y = trapezoid(f, a, b, n) declares the function. The output is named y — the function assigns to y and the value of y at the end of the call is returned. The arguments f, a, b, n are positional. The file is named trapezoid.m, matching the function name; the name in the file must match the file name for the principal function.

The first contiguous block of comments after the function line is the H1 line and help text, returned by help trapezoid and indexed by lookfor. The convention is for the H1 line to be a single-line summary and for subsequent lines to expand on usage.

The end keyword that terminates the function is optional in the older style for a file containing a single function, but is mandatory once the file contains local functions or nested functions, or whenever the function declares an arguments block. The modern recommendation is to always use end.

Multiple outputs

A function may return multiple values; the syntax wraps them in brackets:

function [m, idx] = argmax(x)
    [m, idx] = max(x);
end

The caller chooses how many outputs to take:

m = argmax(x);              % takes only the first output
[m, i] = argmax(x);         % takes both

The function may consult nargout to learn how many outputs were requested — useful when later outputs are expensive to compute:

function [m, idx] = argmax(x)
    m = max(x);
    if nargout > 1
        [~, idx] = max(x);
    end
end

The ~ placeholder ignores an output; the call [~, i] = argmax(x) takes only the index.

varargin and varargout

For variable-length argument lists, the special names varargin and varargout collect trailing arguments into cell arrays:

function result = combine(varargin)
    result = 0;
    for k = 1:nargin
        result = result + sum(varargin{k}(:));
    end
end

combine(1, 2, 3, [4 5 6])       % 21

nargin reports the number of input arguments; for a function with explicit named arguments followed by varargin, the explicit arguments precede the cell. By convention, varargin is the last declared parameter.

Default values and optional arguments

MATLAB has no syntactic support for default values in the function declaration. The conventional patterns:

function y = myFun(x, scale)
    if nargin < 2
        scale = 1;
    end
    y = scale * x;
end

Since R2019b the arguments block (below) provides a cleaner mechanism with defaults. For functions that take many optional parameters, the name-value pair convention — also formalised in the arguments block — is the idiomatic substitute for keyword arguments.

Argument validation blocks (R2019b+)

The modern, recommended form for function signatures:

function y = scaleSquare(x, opts)
    arguments
        x (:, :) double {mustBeFinite}
        opts.scale (1, 1) double = 1
        opts.offset (1, 1) double = 0
    end
    y = opts.scale * x .^ 2 + opts.offset;
end

scaleSquare([1 2 3])                              % [1 4 9]
scaleSquare([1 2 3], 'scale', 2, 'offset', 1)    % [3 9 19]

Several mechanisms are visible:

  • x (:, :) double — type and size validation. (:, :) is any 2-d shape; (1, 1) is scalar; (1, :) is a row vector; (:, 1) is a column.
  • {mustBeFinite} — a validation function. The standard library ships dozens: mustBeFinite, mustBeNumeric, mustBePositive, mustBeInteger, mustBeMember(x, ["a", "b"]). Custom validators are functions that error on invalid input.
  • opts.scale (1, 1) double = 1 — a name-value parameter, gathered into the struct opts. The default is 1.

The block runs before the function body; failures raise informative errors that name the failing argument. It is the standard form in code written from R2019b onwards.

Anonymous functions

An anonymous function is an expression-bodied function defined inline:

f = @(x) x.^2 + 1;
f(3)                        % 10
arrayfun(@(k) k^2, 1:5)     % [1 4 9 16 25]

The @(args) expr form captures the surrounding workspace by value at the moment of construction. The result is a function_handle. Anonymous functions are covered at length in Anonymous functions and handles.

Local functions

A .m file may contain local functions after the principal function. They are visible only inside the file:

% File: outer.m
function out = outer(x)
    out = helper(x) + 1;
end

function y = helper(x)         % local function, visible only in outer.m
    y = x^2;
end

Local functions enable file-private decomposition: a function may use a helper without polluting the global namespace. Since R2016b they are also permitted in scripts.

Nested functions

A nested function is defined inside another function and has access to the enclosing function’s workspace:

function out = counter(start)
    n = start;
    out = @increment;        % return a handle to the nested function

    function y = increment()
        n = n + 1;            % can read and write n in the enclosing workspace
        y = n;
    end
end

c = counter(10);
c()                          % 11
c()                          % 12

The mechanism is the cleanest form of stateful closure available in MATLAB. Nested functions are most commonly used for callbacks that share state with the enclosing function.

Function handles

A function is reified as a value by prefixing its name with @:

f = @sin;
f(pi/4)                      % 0.7071...

g = @trapezoid;
g(@cos, 0, pi, 100)          % numerical integral of cos from 0 to pi

The mechanism is the basis of all higher-order programming: arrayfun, cellfun, fzero, fminunc, ode45, and many others accept function handles. See Anonymous functions and handles.

Scripts that live in functions

A script — a .m file without a leading function — executes in the base workspace. Most production code is a function; scripts are reserved for the entry point of an analysis or a demo. The two styles coexist: a small project might consist of one driver script that calls many functions defined in separate files.

The notable exception is the Live Script (.mlx) — a notebook-style document combining code, formatted text, and inline figures, edited in the MATLAB editor’s two-pane view. Live scripts are a powerful form of literate programming and are increasingly the preferred form for documented numerical work.