eval and Its Alternatives
|
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 sessions below were run in GNU Octave 11.3.0 and show Octave’s output. The MATLAB-specific statements (compilation, transparency, the restrictions in parfor and arguments blocks) are checked against the R2026b documentation and are "not run here".
eval(expression) runs the text in expression as MATLAB code. It is powerful because the program can build code while it runs, and that is also why it is rarely the right tool. The documentation page Alternatives to the eval Function gives the reasons and the replacements, and this page follows it.
Why avoid eval
-
Performance. MATLAB compiles code the first time it runs to speed up later runs, but code in an
evalstatement can change at run time, so it is not compiled. -
Overwriting data. Code inside
evalcan unexpectedly create or assign a variable that already exists in the current workspace. -
Readability. A statement assembled by concatenating character vectors is hard to read, hard to debug and invisible to the Code Analyzer, which cannot check text inside a string (see Code Analyzer and Code Quality).
-
Transparency. MATLAB cannot see which variables an
evalreads or creates until it runs (see below), so some contexts reject it. -
Security. The reference page for
evalwarns that before calling it with untrusted input (data from a user you do not know or from a source you do not control) you must validate the input: first search for the allowed operations, then reject everything else, or replaceevalwith an alternative. In an application, never pass text taken from a file, a network request or a user toeval.
The same applies to evalin(workspace,expression) (the expression runs in the "base" or "caller" workspace) and evalc (which also captures the printed output). The reference page for eval also has two limitations to know: inside an anonymous function, a nested function or a function that contains a nested function, the evaluated expression does not create any variables; and eval with an output list is preferred to building an assignment inside the text. Write output = eval(expression), not eval(["output = ", expression]), so the parser can check the statement.
v = eval("2^10")
try
eval("1 +")
catch err
disp("caught a parse error")
end
Octave 11.3.0 output:
v = 1024
caught a parse error
Variables with sequential names: an array or a cell array
The most frequent use of eval is to make A1, A2, …, An. It throws away what MATLAB is good at. Keep related data in one variable; if the pieces have different types or sizes, use a cell array or a structure array.
% not recommended: A1, A2, A3 created by eval
for n = 1:3
eval(sprintf("A%d = magic(%d);", n, n));
end
disp(A3)
% recommended: one cell array
C = cell(3,1);
for n = 1:3
C{n} = magic(n);
end
disp(C{3})
Octave 11.3.0 output (the same matrix twice):
8 1 6
3 5 7
4 9 2
8 1 6
3 5 7
4 9 2
With the cell array, C{n} reads element n with an ordinary index, a loop can visit all of them (for k = 1:numel©), cellfun can apply a function to all of them, and the whole set can be passed to a function as one argument. See Cell Arrays and Structures.
Files with sequential names: function syntax and sprintf
The command form save myfile1.mat passes its words as character vectors, so a program that wants to put a number in the name is tempted to build the command with eval. Use the function form, which takes variables as arguments, and build the name with sprintf (usually more efficient than int2str):
numFiles = 10;
for n = 1:numFiles
randomData = rand(n);
currentFile = sprintf("run%02d.mat", n);
save(currentFile, "randomData")
end
Not run here (it writes ten files); the loop follows the pattern of the documentation page. The reasons and the rules for command syntax versus function syntax are on Syntax, Statements and Variables; reading a sequence of files is on Workspace Variables and MAT-Files.
Function names in variables: feval and function handles
When the name of the function to call is in a variable, two constructs are more efficient and clearer than eval.
-
A function handle, made with
@or withstr2func. A handle can be stored in a cell array or a structure and called like a function:h = @max; h(x).str2func("min")makes a handle from a character vector or string. -
feval:[y1,...,yN] = feval(fun,x1,...,xM)calls a function given by its name or by its handle with the argumentsx1,...,xM.fevalfollows the same scoping and precedence rules as calling a handle directly (see Function Precedence and Name Resolution).
feval("max", [4 9 2])
h = str2func("min");
h([4 9 2])
f = @max;
f([4 9 2])
Octave 11.3.0 output:
ans = 9
ans = 2
ans = 9
A handle is best when the choice is made in code, and feval or str2func when the name arrives as text. If the text comes from outside the program, check it against a list of allowed names first (ismember(name, ["max" "min"])), because feval with an arbitrary name is still a way to run arbitrary functions. See Anonymous Functions and Function Handles.
Field names in variables: dynamic field names
To read or write a structure field whose name is in a variable, put the expression in parentheses after the dot: s.(name). The heatflow configuration shows it.
cfg.nx = 40; cfg.ny = 20;
name = "nx";
cfg.(name)
cfg.("ny") = 25;
disp(cfg)
Octave 11.3.0 output:
ans = 40
nx = 40
ny = 25
getfield and setfield do the same with function syntax, fieldnames lists the names, and isfield(cfg,name) tests one before use. The error for a missing field has the identifier MATLAB:nonExistentField (wording varies by release, not run here).
Error handling: try and catch
Older documentation of eval included the form eval(expression,catch_expr), which runs catch_expr if expression errors. The current page says an explicit try/catch is significantly clearer and that the implicit catch is not recommended.
try
B = undefinedVariable1;
catch err
disp("A is undefined")
end
Octave 11.3.0 output: A is undefined. In MATLAB the caught error has the identifier MATLAB:UndefinedFunction (not run here). See Errors, Warnings and Exceptions.
evalin and assignin: reaching into another workspace
evalin(ws,expression) evaluates text in the "base" or "caller" workspace, and assignin(ws,"name",value) stores a value there. They break the isolation that makes functions understandable: a function that reads a variable of its caller by name has a hidden input, and one that creates a variable in its caller has a hidden output. The replacement is to pass data through arguments and return values, or to share state in an object (see Workspaces, Scope, Global and Persistent Variables). They do work, and a debugging helper may legitimately use them:
demo
function demo
total = 5;
helper
disp(total)
end
function helper
v = evalin("caller", "total");
fprintf("helper sees %d\n", v);
assignin("caller", "total", v + 1);
end
The file is a script: its first statement is the call to demo, and the local functions follow at the end of the file, which MATLAB accepts in every release that has local functions in scripts (a file that begins with function would be a function file instead; see Scripts and Code Sections). Octave needs a function to be defined before a script calls it, so the run used the same functions placed before the call, after a 1; line. Octave 11.3.0 output:
helper sees 5
6
helper is a function with an invisible dependence on a variable called total in whoever calls it, which is the problem. evalin("base",...) and assignin("base",...) are worse because they reach the interactive workspace from anywhere.
Transparency
Code has transparent variable access if MATLAB can identify every variable access, including reading, adding, removing or modifying workspace variables, by scanning the code while ignoring comments, character vectors and string literals. In X = zeros(1,10) followed by a loop with X(ii) = randi(9,1), MATLAB can see X and ii are variables. In eval('X(ii) = randi(9,1);') it sees only a call to eval with one character-vector argument, and has to run it to learn that X and ii are variables.
MATLAB requires transparent access in these contexts, and a nontransparent access raises a run-time error:
-
function argument validation blocks (see Argument Validation);
-
the body of a
parforloop or anspmdblock (Parallel Computing Toolbox, mentioned only; this section does not use it, see Toolboxes and Add-On Products).
The documentation lists what is not transparent:
-
eval,evalc,evalinandassignin; -
scripts;
-
MEX functions that access workspace variables dynamically, for example with
mexGetVariable; -
introspective functions such as
whoandwhos; -
the
saveandloadcommands, except when the result ofloadis assigned explicitly; -
any dynamic name reference;
-
passing a variable by command form, because that is equivalent to passing a character string: both
clear Xandclear('X')are nontransparent.
load foo.mat is nontransparent because MATLAB cannot know which variables the file holds, but S = load("foo.mat") or X = load("foo.mat","X") assigns the result explicitly and is transparent. The same goes for any assignment to a variable that you name on the left-hand side. Writing transparent code is the same advice as the rest of this page: name variables in the code, and let MATLAB (and the Code Analyzer) see them.
Pitfalls
-
Building variable names (
A1,A2) withevalwhen a cell array, structure array or matrix would do. -
evalon text from outside the program: validate, or avoid it. The risk is arbitrary code execution. -
Building an assignment in the text (
eval(["x = ", expr])): usex = eval(expr). -
evalcreating a variable inside an anonymous or nested function: it does not. -
evalwith a catch string: usetryandcatch. -
evalin("base",...)andassignin("base",...)as a way to share data: pass arguments and return values. -
loadwithout an output inside a function: MATLAB cannot see which variables it creates. Assign the result. -
A keyword used as a name:
evalruns whole statements, keywords included (eval("for k=1:3, disp(k), end")works), but text that uses a keyword as a variable or field name, such asend = 5, is a syntax error.iskeywordtells whether a name is reserved, andmatlab.lang.makeValidNameturns arbitrary text into a valid name.
Where older books differ
Older books present eval as the general way to run text and to make families of variables, and show eval(try,catch). The current documentation says the opposite: it recommends the alternatives on this page, calls the implicit catch not recommended and adds the security warning. Books also predate the transparency requirement of arguments blocks.