Anonymous functions are a powerful tool of the MATLAB language. They are functions that exist locally, that is: in the current workspace. However, they do not exist on the MATLAB path like a regular function would, e.g. in an m-file. That is why they are called anonymous, although they can have a name like a variable in the workspace.
@
operatorUse the @
operator to create anonymous functions and function handles. For example, to create a handle to the sin
function (sine) and use it as f
:
>> f = @sin
f =
@sin
Now f
is a handle to the sin
function. Just like (in real life) a door handle is a way to use a door, a function handle is a way to use a function. To use f
, arguments are passed to it as if it were the sin
function:
>> f(pi/2)
ans =
1
f
accepts any input arguments the sin
function accepts. If sin
would be a function that accepts zero input arguments (which it does not, but others do, e.g. the peaks
function), f()
would be used to call it without input arguments.
It is not obviously useful to create a handle to an existing function, like sin
in the example above. It is kind of redundant in that example. However, it is useful to create anonymous functions that do custom things that otherwise would need to be repeated multiple times or created a separate function for. As an example of a custom anonymous function that accepts one variable as its input, sum the sine and cosine squared of a signal:
>> f = @(x) sin(x)+cos(x).^2
f =
@(x)sin(x)+cos(x).^2
Now f
accepts one input argument called x
. This was specified using parentheses (...)
directly after the @
operator. f
now is an anonymous function of x
: f(x)
. It is used by passing a value of x
to f
:
>> f(pi)
ans =
1.0000
A vector of values or a variable can also be passed to f
, as long as they are used in a valid way within f
:
>> f(1:3) % pass a vector to f
ans =
1.1334 1.0825 1.1212
>> n = 5:7;
>> f(n) % pass n to f
ans =
-0.8785 0.6425 1.2254
In the same fashion anonymous functions can be created to accept more than one variable. An example of an anonymous function that accepts three variables:
>> f = @(x,y,z) x.^2 + y.^2 - z.^2
f =
@(x,y,z)x.^2+y.^2-z.^2
>> f(2,3,4)
ans =
-3
Variables in the workspace can be used within the definition of anonymous functions. This is called parameterizing. For example, to use a constant c = 2
in an anonymous function:
>> c = 2;
>> f = @(x) c*x
f =
@(x)c*x
>> f(3)
ans =
6
f(3)
used the variable c
as a parameter to multiply with the provided x
. Note that if the value of c
is set to something different at this point, then f(3)
is called, the result would not be different. The value of c
is the value at the time of creation of the anonymous function:
>> c = 2;
>> f = @(x) c*x;
>> f(3)
ans =
6
>> c = 3;
>> f(3)
ans =
6
Note that using the name of variables in the workspace as one of the input arguments of an anonymous function (i.e., using @(...)
) will not use those variables' values. Instead, they are treated as different variables within the scope of the anonymous function, that is: the anonymous function has its private workspace where the input variables never refer to the variables from the main workspace. The main workspace and the anonymous function's workspace do not know about each other's contents. An example to illustrate this:
>> x = 3 % x in main workspace
x =
3
>> f = @(x) x+1; % here x refers to a private x variable
>> f(5)
ans =
6
>> x
x =
3
The value of x
from the main workspace is not used within f
. Also, in the main workspace x
was left untouched. Within the scope of f
, the variable names between parentheses after the @
operator are independent from the main workspace variables.
An anonymous function (or, more precisely, the function handle pointing at an anonymous function) is stored like any other value in the current workspace: In a variable (as we did above), in a cell array ({@(x)x.^2,@(x)x+1}
), or even in a property (like h.ButtonDownFcn
for interactive graphics). This means the anonymous function can be treated like any other value. When storing it in a variable, it has a name in the current workspace and can be changed and cleared just like variables holding numbers.
Put differently: A function handle (whether in the @sin
form or for an anonymous function) is simply a value that can be stored in a variable, just like a numerical matrix can be.
Since function handles are treated like variables, they can be passed to functions that accept function handles as input arguments.
An example: A function is created in an m-file that accepts a function handle and a scalar number. It then calls the function handle by passing 3
to it and then adds the scalar number to the result. The result is returned.
Contents of funHandleDemo.m
:
function y = funHandleDemo(fun,x)
y = fun(3);
y = y + x;
Save it somewhere on the path, e.g. in MATLAB's current folder. Now funHandleDemo
can be used as follows, for example:
>> f = @(x) x^2; % an anonymous function
>> y = funHandleDemo(f,10) % pass f and a scalar to funHandleDemo
y =
19
The handle of another existing function can be passed to funHandleDemo
:
>> y = funHandleDemo(@sin,-5)
y =
-4.8589
Notice how @sin
was a quick way to access the sin
function without first storing it in a variable using f = @sin
.
bsxfun
, cellfun
and similar functions with anonymous functionsMATLAB has some built-in functions that accept anonymous functions as an input. This is a way to perform many calculations with a minimal number of lines of code. For example bsxfun
, which performs element-by-element binary operations, that is: it applies a function on two vectors or matrices in an element-by-element fashion. Normally, this would require use of for
-loops, which often requires preallocation for speed. Using bsxfun
this process is sped up. The following example illustrates this using tic
and toc
, two functions that can be used to time how long code takes. It calculates the difference of every matrix element from the matrix column mean.
A = rand(50); % 50-by-50 matrix of random values between 0 and 1
% method 1: slow and lots of lines of code
tic
meanA = mean(A); % mean of every matrix column: a row vector
% pre-allocate result for speed, remove this for even worse performance
result = zeros(size(A));
for j = 1:size(A,1)
result(j,:) = A(j,:) - meanA;
end
toc
clear result % make sure method 2 creates its own result
% method 2: fast and only one line of code
tic
result = bsxfun(@minus,A,mean(A));
toc
Running the example above results in two outputs:
Elapsed time is 0.015153 seconds.
Elapsed time is 0.007884 seconds.
These lines come from the toc
functions, which print the elapsed time since the last call to the tic
function.
The bsxfun
call applies the function in the first input argument to the other two input arguments. @minus
is a long name for the same operation as the minus sign would do. A different anonymous function or handle (@
) to any other function could have been specified, as long as it accepts A
and mean(A)
as inputs to generate a meaningful result.
Especially for large amounts of data in large matrices, bsxfun
can speed up things a lot. It also makes code look cleaner, although it might be more difficult to interpret for people who don't know MATLAB or bsxfun
. (Note that in MATLAB R2016a and later, many operations that previously used bsxfun
no longer need them; A-mean(A)
works directly and can in some cases be even faster.)