Why Can an Anonymous Function be Defined with a Non-Existent Parameter?

Define an anonymous function with one argument (x) and one parameter (y)
f = @(x) x + y;
I'm suprised that line sails through without an error (or even a warning) even though there is no variable called y in the workspace at the time f() is defined.
Calling f results in an error (unsurprisingly)
try
f(2)
catch ME
ME.message
end
ans = 'Unrecognized function or variable 'y'.'
Once f() is defined, I don't believe there is any way to subsequently define y such that f() works.
Would it be better if an error (or at least a warning) is generated at the time of function definition rather than at the time of function execution?

 Accepted Answer

Once f() is defined, I don't believe there is any way to subsequently define y such that f() works.
Sure there is. Let's first reproduce the failure:
which -all y % It doesn't exist
'y' not found.
f = @(x) x+y;
try
f(1) % This will error
catch ME
fprintf("Error: %s\n", ME.message)
end
Error: Unrecognized function or variable 'y'.
So it does in fact throw an error. Now let's make it work. Note that the only reference to f below is when I call it; I haven't changed the definition of f at all.
cd(tempdir)
fid = fopen('y.m', 'wt');
fprintf(fid, "function z = y\nz = pi;\n");
fclose(fid);
Is y now defined?
which -all y
/tmp/y.m
What is it?
dbtype y.m
1 function z = y 2 z = pi;
Can we call f?
result = f(1) % pi + 1
result = 4.1416
Does it have the value we expect it should if it called the y.m function I created above?
result == (pi + 1) % true
ans = logical
1
Instead of writing y.m, I could have added a folder with a y function to the MATLAB search path or cd to such a folder.

7 Comments

Thanks. I hadn't thought of this case where y is defined as m-function.
@Steven Lord, why does MATLAB allow to define an anonymous function with an un-defined variable/parameter though?
Does MATLAB just assumes that there exists a variable (which the user is aware of) when defining a function handle/anonymous function?
Normally, if you define a function handle with a parameter in it, MATLAB looks to see if a variable with that name exists in your workspace. If so, then it becomes encapsulated in the function handle workspace. But if not, then MATLAB probably assume the undefined variable is a function itself on the search path, and it only tries to resolve that at execution.
John is correct. We can see this using the diagnostic tool known as the functions function. [Don't use this in a programmatic workflow, as per the note on the documentation page.]
x = 1;
f = @(y) x + y + z;
info = functions(f)
info = struct with fields:
function: '@(y)x+y+z+pi' type: 'anonymous' file: '/tmp/Editor_aoxiy/LiveEditorEvaluationHelperEeditorId.m' within_file_path: '' workspace: {[1×1 struct]}
The workspace field inside info contains information about what variables the anonymous function "remembers". [To forestall what I expect someone to ask no, it is not possible to modify the anonymous function's "memory" other than by recreating it.] In this example it only "remembers" the variable x. y is an input argument to the anonymous function. It doesn't "know" what z is when f is created; it will look it up when you try to use the anonymous function.
info.workspace{1}
ans = struct with fields:
x: 1
If you specify an input argument when you call f (so y is defined) and it can find out what z is at that time, the anonymous function call can proceed. If not, it will tell you "I don't know what z is." [I'm paraphrasing, of course.]
Suppose we have an anonymous function defined as
clearvars
f = @(a) a + c + d(a) + e.g;
Is it reasonable to ask what c, d, and e could be at execution time that allows f to execute w/o error?
We know that neither c, d, nor e can be variables in the caller's workspace (in particular, neither c nor d can be function_handles in the caller's workspace, which is a lesson I learned the hard way).
c and d can be m-functions on the search path, as @Steven Lord discussed above.
If f is executed in a script or m-function, can c and d be local functions in the file which f is executing?
Can c or d be private or nested (I've never used these before, so don't know if the question even makes sense)?
I suppose d could be method of the class of a?
e can't be a struct in the caller's workspace. But I suppose it could be a function (m-function, or ?) that returns a struct that has a field g? Any other possibilities for e?
Is it reasonable to ask what c, d, and e could be at execution time that allows f to execute w/o error?
Sure.
We know that neither c, d, nor e can be variables in the caller's workspace (in particular, neither c nor d can be function_handles in the caller's workspace, which is a lesson I learned the hard way).
Because of the clearvars call.
c and d can be m-functions on the search path, as @Steven Lord discussed above.
Correct. They can even be functions that weren't on the path when the anonymous function was created, but are on the path when it is executed.
If f is executed in a script or m-function, can c and d be local functions in the file which f is executing?
Yes. Function handles (and anonymous functions are function handles) "remember" the scope in which they were created. See this documentation page, specifically the last part of the "Creating Function Handles" section. That's why a function can return a function handle to one of its local functions and have that be callable from outside. The local function was in scope when the function handle was created, so it's callable through the function handle.
fh = makeFunctionHandle();
canCallViaFunctionHandle = fh(1:3)
canCallViaFunctionHandle = 1×3
2 4 6
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
try % So I can call stuff later in this comment
cannotCallDirectly = localFunction(1:3) % Not in scope
catch ME
fprintf("Direct call threw error:\n\t%s\n", ME.message)
end
Direct call threw error: Undefined function 'localFunction' for input arguments of type 'double'.
function fh = makeFunctionHandle()
fh = @localFunction;
function y = localFunction(x)
y = x*2;
end
end
Can c or d be private or nested (I've never used these before, so don't know if the question even makes sense)?
Nested: yes. See above. localFunction is nested inside makeFunctionHandle.
Private: I believe so, as long as the function handle was created in a function in the parent folder of the private folder. I have not tried this, though.
I suppose d could be method of the class of a?
Sure. And which class's d method gets called is determined at run-time. For example, if you replaced d(a) with plot(a), well, there are a lot of classes that have a method named plot. [And I'm sure this is not a complete list; user-defined classes, classes in products that aren't supported in the MATLAB instance used by MATLAB Answers to evaluate code, classes that haven't been loaded into memory yet, ...] Thought for this particular example it would need to be a class with both plot and plus methods (due to "a + <stuff>"), which may narrow things down a little.
w = which('plot', '-all')
w = 48×1 cell array
{'built-in (/MATLAB/toolbox/matlab/graphics/graphics/graph2d/plot)'} {'/MATLAB/toolbox/matlab/bigdata/@tall/plot.m' } {'/MATLAB/toolbox/matlab/graphics/math/@polyshape/plot.m' } {'/MATLAB/toolbox/matlab/graphics/math/@digraph/plot.m' } {'/MATLAB/toolbox/matlab/graphics/math/@alphaShape/plot.m' } {'/MATLAB/toolbox/matlab/graphics/math/@graph/plot.m' } {'/MATLAB/toolbox/matlab/timeseries/@timeseries/plot.m' } {'/MATLAB/toolbox/bioinfo/bioinfo/@phytree/plot.m' } {'/MATLAB/toolbox/bioinfo/bioinfo/microarray/@HeatMap/plot.m' } {'/MATLAB/toolbox/bioinfo/bioinfo/microarray/@clustergram/plot.m' } {'/MATLAB/toolbox/curvefit/curvefit/@sfit/plot.m' } {'/MATLAB/toolbox/curvefit/curvefit/@cfit/plot.m' } {'/MATLAB/toolbox/econ/econ/@semiconjugateblm/plot.m' } {'/MATLAB/toolbox/econ/econ/@conjugateblm/plot.m' } {'/MATLAB/toolbox/econ/econ/@customblm/plot.m' } {'/MATLAB/toolbox/econ/econ/@mixsemiconjugateblm/plot.m' } {'/MATLAB/toolbox/econ/econ/@blm/plot.m' } {'/MATLAB/toolbox/econ/econ/@empiricalblm/plot.m' } {'/MATLAB/toolbox/econ/econ/@mixconjugateblm/plot.m' } {'/MATLAB/toolbox/econ/econ/@diffuseblm/plot.m' } {'/MATLAB/toolbox/econ/econ/@lassoblm/plot.m' } {'/MATLAB/toolbox/ident/ident/@iddata/plot.m' } {'/MATLAB/toolbox/ident/nlident/@idnlhw/plot.m' } {'/MATLAB/toolbox/ident/nlident/@idnlarx/plot.m' } {'/MATLAB/toolbox/mbc/mbcdata/@cgrules/plot.m' } {'/MATLAB/toolbox/mbc/mbcmodels/@localmulti/plot.m' } {'/MATLAB/toolbox/mbc/mbcmodels/@xregtransient/plot.m' } {'/MATLAB/toolbox/mbc/mbcmodels/@localavfit/plot.m' } {'/MATLAB/toolbox/mbc/mbcmodels/@xregmodel/plot.m' } {'/MATLAB/toolbox/mbc/mbcmodels/@xregtwostage/plot.m' }
numberOfPlotMethods = numel(w)
numberOfPlotMethods = 48
e can't be a struct in the caller's workspace. But I suppose it could be a function (m-function, or ?) that returns a struct that has a field g? Any other possibilities for e?
Yes, it could be a function that returns a struct into which you directly index. It could also be the name of a namespace with a function named g that can be called with 0 input arguments and 1 output argument. Or it could be the name of a class with a Static method named g that can be called with 0 input arguments and 1 output argument. I'm guessing there's probably something I'm forgetting but I suspect those three are the most likely cases you're going to encounter.
I read the "Creating Function Handles" section and I don't understand how it applies in this discussion. The only function handle in this discussion is f, so I don't understand how that section can answer a question about c, d and e. Are c and d and (possibly) e also function handles?
Also, if e is a function with no input arguments and returns a struct with a field named g, then it still has to be called with parentheses
f = @(a) a + c + d(a) + e().g;
Do you think the doc page Anonymous Functions should be updated? It has a section on "Variables in the Expression," but if c and d and e are not defined at the time f is defined then they are not variables and that section wouldn't apply. Also, this section might want to show an example with variable that's a function handle. Seems like there should be an additional section on "Functions in the Expression" that basically says that function calls (not through function handles) are resolved at execution time using the normal precedence rules (assuming that's the case).

Sign in to comment.

More Answers (0)

Products

Release

R2025a

Asked:

on 6 Jul 2025

Edited:

on 8 Jul 2025

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!