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 eval statement can change at run time, so it is not compiled.

  • Overwriting data. Code inside eval can 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 eval reads or creates until it runs (see below), so some contexts reject it.

  • Security. The reference page for eval warns 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 replace eval with an alternative. In an application, never pass text taken from a file, a network request or a user to eval.

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 with str2func. 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 arguments x1,...,xM. feval follows 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:

The documentation lists what is not transparent:

  • eval, evalc, evalin and assignin;

  • scripts;

  • MEX functions that access workspace variables dynamically, for example with mexGetVariable;

  • introspective functions such as who and whos;

  • the save and load commands, except when the result of load is assigned explicitly;

  • any dynamic name reference;

  • passing a variable by command form, because that is equivalent to passing a character string: both clear X and clear('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) with eval when a cell array, structure array or matrix would do.

  • eval on text from outside the program: validate, or avoid it. The risk is arbitrary code execution.

  • Building an assignment in the text (eval(["x = ", expr])): use x = eval(expr).

  • eval creating a variable inside an anonymous or nested function: it does not.

  • eval with a catch string: use try and catch.

  • evalin("base",...) and assignin("base",...) as a way to share data: pass arguments and return values.

  • load without an output inside a function: MATLAB cannot see which variables it creates. Assign the result.

  • A keyword used as a name: eval runs 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 as end = 5, is a syntax error. iskeyword tells whether a name is reserved, and matlab.lang.makeValidName turns 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.