Anonymous Functions and Function Handles
A function handle (@name) is a value that refers to a function: store it in a variable, pass it to another function, call it later.
Concept
A function handle (@name) is a value that refers to a function: store it in a variable, pass it to another function, call it later.
An anonymous function defines a one-expression function inline: sq = @(x) x.^2. It captures the values of any other variables at the moment it is created (later changes to those variables don't affect it).
Handles are everywhere in MATLAB's numerical library: fzero(@f, x0), integral(@f, a, b), ode45(@rhs, tspan, y0), fminsearch, arrayfun, cellfun, callbacks in GUIs.
arrayfun(@f, A) Apply f to each element of an array cellfun(@f, C) Apply f to each cell of a cell array 'UniformOutput', false
Collect results in a cell array when they aren't scalars func2str, str2func Convert between handles and text
Why It Matters
Handles let you write general tools (a solver, an optimizer, a test runner) that work with any model function — the core of numerical engineering code.
Syntax
f = @(t, y) -2 * y; % anonymous
h = @sin; % handle to a named function
integral(f_of_x, 0, 1); % pass as an argument
C = cellfun(@upper, names, 'UniformOutput', false);Example
12.1 Anonymous functions, captured variables, handles as arguments
sq = @(x) x .^ 2; % anonymous function
fprintf('sq(4) = %g, sq([1 2 3]) = %s\n', sq(4), mat2str(sq([1 2 3])))
g = 9.81;
fall = @(t) 0.5 * g * t .^ 2; % captures g's value at creation
g = 1.62;
fprintf('fall(2) = %.2f m (still uses g = 9.81)\n', fall(2))
h = @celsius_to_fahrenheit; % handle to a named function
fprintf('h(37) = %.1f, func2str(sq) = %s\n', h(37), func2str(sq))
apply = @(f, v) f(v); % functions as arguments
fprintf('apply(@sqrt, 81) = %g\n', apply(@sqrt, 81))
fprintf('arrayfun: %s\n', mat2str(arrayfun(@(k) k * 10, 1:4)))
lens = cellfun(@length, {'VCU', 'BMS', 'Gateway'});
fprintf('cellfun lengths: %s\n', mat2str(lens))
up = cellfun(@upper, {'vcu', 'bms'}, 'UniformOutput', false);
fprintf('cellfun with UniformOutput false: %s\n', strjoin(up, ', '))
fprintf('fzero(@(x) x^2 - 2, 1) = %.6f\n', fzero(@(x) x^2 - 2, 1))
fprintf('integral of sin from 0 to pi = %.6f\n', integral(@sin, 0, pi))
compose = @(f, g2) @(x) f(g2(x));
kmh_rounded = compose(@round, @(mps) mps * 3.6);
fprintf('compose: 27.78 m/s -> %d km/h\n', kmh_rounded(27.78))Expected Result
fall kept using g = 9.81 even after g was changed to 1.62: anonymous functions capture values when created. fzero and integral both took a handle as their first argument.
sq(4) = 16, sq([1 2 3]) = [1 4 9]
fall(2) = 19.62 m (still uses g = 9.81)
h(37) = 98.6, func2str(sq) = @(x) x .^ 2
apply(@sqrt, 81) = 9
arrayfun: [10 20 30 40]
cellfun lengths: [3 3 7]
cellfun with UniformOutput false: VCU, BMS
fzero(@(x) x^2 - 2, 1) = 1.414214
integral of sin from 0 to pi = 2.000000
compose: 27.78 m/s -> 100 km/hCommon Mistakes
Using * instead of .* inside an anonymous function that must work on vectors.
Expecting an anonymous function to see later changes of captured variables.
cellfun failing with "non-uniform output" — add 'UniformOutput', false.
Multi-statement logic in an anonymous function (not allowed; write a normal function).
Best Practices
Keep anonymous functions short; name complex ones as proper functions.
Parameterize models by capturing parameters: rhs = @(t, y) model(t, y, p).
Prefer vectorized code over arrayfun in performance-critical paths (arrayfun is convenient, not always fast).
Interview Relevance
Medium–high: "what is a function handle?", "what does an anonymous function capture?", "how do you pass a function to fzero/ode45?", "arrayfun vs cellfun?".
Practice Questions
Create f = @(x, y) x.^2 + y.^2 and evaluate it on a meshgrid.
Use cellfun to find which names in a cell array start with 'B'.
Write a function apply_twice(f, x) that returns f(f(x)).
Build a cell array of handles {@sin, @cos, @tan} and evaluate each at pi/4.
Quick Quiz
Q1. (Multiple choice) @(x) x.^2 is: A) A string B) A function handle to an anonymous function C) A cell D) A struct Answer: B.
Q2. (Predict the output) g = 9.81; f = @(t) 0.5*g*t^2; g = 1.62; f(2)
Answer: 19.62 — g was captured as 9.81 (verified).
Q3. (True/False) cellfun(@upper, {'a','bc'}) works without extra options.
Answer: False. The outputs aren't scalars; use 'UniformOutput', false.
Q4. (Find the bug) f = @(x) x^2; f([1 2 3]) errors.
Answer: x^2 is a matrix power; use x.^2.
Coding Challenge
Write a function-handle-based numerical derivative d = @(f, x, h) (f(x + h) - f(x - h)) / (2*h) and use it to approximate the derivative of exp and sin at 1, comparing with the exact values.
d = @(f, x, h) (f(x + h) - f(x - h)) / (2 * h);
fprintf('d/dx exp at 1: %.8f (exact %.8f)\n', d(@exp, 1, 1e-5), exp(1))
fprintf('d/dx sin at 1: %.8f (exact %.8f)\n', d(@sin, 1, 1e-5), cos(1))