As an experiment (and because I'm generating anonymous functions off of user data) I ran the following MATLAB code:
h = #(x) x * x
h = #(x) x * x
h(3)
ans = 9
h = #(x) h(x) + 1
h = #(x)h(x)+1
h(3)
ans = 10
Basically, I made an anonymous function call itself. Instead of acting recursively, MATLAB remembered the old function definition. However, the workspace doesn't show it as one of the variables, and the handle doesn't seem to know it either.
Will the old function be stored behind the scenes as long as I keep the new one? Are there any "gotchas" with this kind of construction?
An anonymous function remembers the relevant part of the workspace at the time of definition, and makes a copy of it. Thus, if you include a variable in the definition of the anonymous function, and change that variable later, it will keep the old value inside the anonymous function.
>> a=1;
>> h=#(x)x+a %# define an anonymous function
h =
#(x)x+a
>> h(1)
ans =
2
>> a=2 %# change the variable
a =
2
>> h(1)
ans =
2 %# the anonymous function does not change
>> g = #()length(whos)
g =
#()length(whos)
>> g()
ans =
0 %# the workspace copy of the anonymous function is empty
>> g = #()length(whos)+a
g =
#()length(whos)+a
>> g()
ans =
3 %# now, there is something in the workspace (a is 2)
>> g = #()length(whos)+a*0
g =
#()length(whos)+a*0
>> g()
ans =
1 %# matlab doesn't care whether it is necessary to remember the variable
>>
Related
MATLAB stores variables along with anonymous functions. Here is an example of how this works from the documentation.
Variables in the Expression:
Function handles can store not only an expression, but also variables
that the expression requires for evaluation.
For example, create a function handle to an anonymous function that
requires coefficients a, b, and c.
a = 1.3;
b = .2;
c = 30;
parabola = #(x) a*x.^2 + b*x + c;
Because a, b, and c are available at the time you create parabola, the
function handle includes those values. The values persist within the
function handle even if you clear the variables:
clear a b c
x = 1;
y = parabola(x)
y =
31.5000
Supposedly, the values of a b and c are stored with the function even when it's saved and reloaded from a mat file. In practice, I've found that these values do not persist, especially if the code that originally created the function is edited.
Is there a way to define the function handle in terms of the numeric values of the variables? I would like something of the form
>> a = 1.3;
>> b = .2;
>> c = 30;
>> parabola = #(x) a*x.^2 + b*x + c
parabola = #(x) a*x.^2+b*x+c
>> parabola2 = forceEval(parabola)
parabola2 = #(x) 1.3*x.^2+.2x+30
EDIT: Perhaps my problem is with the file association, but when I edit the file that I originally defined the anonymous function in, I get an error that looks like:
Unable to find function #(ydata)nr/(na*dt)*normpdf(ydata,mu(j),s(j))./normpdf(ydata,mu_a(j),s_a(j)) within
C:...\mfilename.m. (where I've changed the name of my mfile to mfilename)
My usual solution to this kind of stuff has been to use func2str() to remove the file dependency, but this also strips out the workspace information including the parameter values. So I would like to force all the parameters to take on their numerical values in the function definition.
The values are stored in the function. As I've demonstrated in different answers before, you can check this with the functions command:
>> a = 1.3; b = .2; c = 30;
>> parabola = #(x) a*x.^2 + b*x + c;
>> x = 1;
>> y = parabola(x)
y =
31.5
>> clear a b c
>> y = parabola(x)
y =
31.5
>> fi = functions(parabola)
fi =
function: '#(x)a*x.^2+b*x+c'
type: 'anonymous'
file: ''
workspace: {[1x1 struct]}
>> fi.workspace{1}
ans =
a: 1.3
b: 0.2
c: 30
Even when you save the handle to disk:
>> save parabolaFun.mat parabola
>> clear parabola a b c
>> load parabolaFun.mat parabola
>> y = parabola(x)
y =
31.5
>> fi = functions(parabola)
fi =
function: '#(x)a*x.^2+b*x+c'
type: 'anonymous'
file: ''
workspace: {[1x1 struct]}
>> fi.workspace{1}
ans =
a: 1.3
b: 0.2
c: 30
And you can simplify the creation of a parabola handle like this:
function p = makeParabola(a,b,c)
p = #(x) a*x.^2 + b*x + c;
end
There are certain caveats:
You can save and load function handles in a MAT-file using the MATLABĀ® save and load functions. If you load a function handle that you saved in an earlier MATLAB session, the following conditions could cause unexpected behavior:
Any of the files that define the function have been moved, and thus no longer exist on the path stored in the handle.
You load the function handle into an environment different from that in which it was saved. For example, the source for the function either does not exist or is located in a different folder than on the system on which the handle was saved.
In both of these cases, the function handle is now invalid because it is no longer associated with any existing function code. Although the handle is invalid, MATLAB still performs the load successfully and without displaying a warning. Attempting to invoke the handle, however, results in an error.
Hence, if you create the handle from a file-backed function (not a script, that's OK), and then modify or delete the file, the handle will become invalid.
Anonymous functions capture the values of all variables involved in the expression. If you want to see the environment workspace captured, use functions as #chappjc showed in his answer.
Now you gotta be careful about the type of variables used in the anonymous function (think value-type vs. handle-type).
All native types (numerics, logicals, structs, cells, etc..) are captured by-value not by-reference. Example:
x = magic(4);
f = #() x; % captures matrix x
x(1) = 1 % modify x
xx = f() % change not reflected here
Compare that to using handle-class types (e.g containers.Map):
x = containers.Map('KeyType','char', 'ValueType','double');
f = #() x; % captures handle-class object x
x('1') = 1; % modify map
keys(x) % changed
keys(f()) % also changed!
f() == x % compare handle equality, evaluates to true
a = 1.3, b = 0.2, c = 30;
parabola = eval(['#(x) ', num2str(a), '*x^2 + ', num2str(b), '*x + ', num2str(c)]);
In a previous question, a user asked about iterating over a cell array of anonymous functions. I am wondering whether there is a way to evaluate a set of functions without the explicit use of a for loop.
As an example, the following code creates an array of (simple) functions, evaluates them for a fixed value and stores the results:
fcnList = {#(x) (x+1), #(x) (x+2)};
a = 2;
for i = 1:numel(fcnList)
y(i) = fcnList{i}(a);
end
Is there a way to do this without looping?
For your example, you could do the following using the cellfun function:
fcnList = {#(x) (x+1), #(x) (x+2)};
a = 2;
cellfun(#(func) func(a),fcnList)
ans =
3 4
Where I have created a handle called func which accepts as input a function from the fcnList variable. Each function is then evaluated for a.
If you need to pass a vector instead of a scalar, for instance b, you will need to set the 'UniformOutput' option to false:
b=[3 4]
fcnList = {#(x) (x+1), #(x) (x+2)};
cellfun(#(func) func(b),fcnList,'UniformOutput',false)
ans =
{
[1,1] =
4 5
[1,2] =
5 6
}
To avoid a for loop or cellfun (which is more or less the same as a loop), you can define a single function with vector output:
fcn = #(x) [x+1, x+2];
Then fcn(a) gives you a vector cointaining the results:
>> fcn = #(x) [x+1, x+2];
>> a = 2;
>> fcn(a)
ans =
3 4
If the results of each original function have different sizes you can define a single function with cell array output:
>> fcn = #(x) {x+1, [x+2; x+3]};
>> a = 2;
>> x = fcn(a)
x =
[3] [2x1 double]
>> celldisp(x)
x{1} =
3
x{2} =
4
5
MATLAB stores variables along with anonymous functions. Here is an example of how this works from the documentation.
Variables in the Expression:
Function handles can store not only an expression, but also variables
that the expression requires for evaluation.
For example, create a function handle to an anonymous function that
requires coefficients a, b, and c.
a = 1.3;
b = .2;
c = 30;
parabola = #(x) a*x.^2 + b*x + c;
Because a, b, and c are available at the time you create parabola, the
function handle includes those values. The values persist within the
function handle even if you clear the variables:
clear a b c
x = 1;
y = parabola(x)
y =
31.5000
Supposedly, the values of a b and c are stored with the function even when it's saved and reloaded from a mat file. In practice, I've found that these values do not persist, especially if the code that originally created the function is edited.
Is there a way to define the function handle in terms of the numeric values of the variables? I would like something of the form
>> a = 1.3;
>> b = .2;
>> c = 30;
>> parabola = #(x) a*x.^2 + b*x + c
parabola = #(x) a*x.^2+b*x+c
>> parabola2 = forceEval(parabola)
parabola2 = #(x) 1.3*x.^2+.2x+30
EDIT: Perhaps my problem is with the file association, but when I edit the file that I originally defined the anonymous function in, I get an error that looks like:
Unable to find function #(ydata)nr/(na*dt)*normpdf(ydata,mu(j),s(j))./normpdf(ydata,mu_a(j),s_a(j)) within
C:...\mfilename.m. (where I've changed the name of my mfile to mfilename)
My usual solution to this kind of stuff has been to use func2str() to remove the file dependency, but this also strips out the workspace information including the parameter values. So I would like to force all the parameters to take on their numerical values in the function definition.
The values are stored in the function. As I've demonstrated in different answers before, you can check this with the functions command:
>> a = 1.3; b = .2; c = 30;
>> parabola = #(x) a*x.^2 + b*x + c;
>> x = 1;
>> y = parabola(x)
y =
31.5
>> clear a b c
>> y = parabola(x)
y =
31.5
>> fi = functions(parabola)
fi =
function: '#(x)a*x.^2+b*x+c'
type: 'anonymous'
file: ''
workspace: {[1x1 struct]}
>> fi.workspace{1}
ans =
a: 1.3
b: 0.2
c: 30
Even when you save the handle to disk:
>> save parabolaFun.mat parabola
>> clear parabola a b c
>> load parabolaFun.mat parabola
>> y = parabola(x)
y =
31.5
>> fi = functions(parabola)
fi =
function: '#(x)a*x.^2+b*x+c'
type: 'anonymous'
file: ''
workspace: {[1x1 struct]}
>> fi.workspace{1}
ans =
a: 1.3
b: 0.2
c: 30
And you can simplify the creation of a parabola handle like this:
function p = makeParabola(a,b,c)
p = #(x) a*x.^2 + b*x + c;
end
There are certain caveats:
You can save and load function handles in a MAT-file using the MATLABĀ® save and load functions. If you load a function handle that you saved in an earlier MATLAB session, the following conditions could cause unexpected behavior:
Any of the files that define the function have been moved, and thus no longer exist on the path stored in the handle.
You load the function handle into an environment different from that in which it was saved. For example, the source for the function either does not exist or is located in a different folder than on the system on which the handle was saved.
In both of these cases, the function handle is now invalid because it is no longer associated with any existing function code. Although the handle is invalid, MATLAB still performs the load successfully and without displaying a warning. Attempting to invoke the handle, however, results in an error.
Hence, if you create the handle from a file-backed function (not a script, that's OK), and then modify or delete the file, the handle will become invalid.
Anonymous functions capture the values of all variables involved in the expression. If you want to see the environment workspace captured, use functions as #chappjc showed in his answer.
Now you gotta be careful about the type of variables used in the anonymous function (think value-type vs. handle-type).
All native types (numerics, logicals, structs, cells, etc..) are captured by-value not by-reference. Example:
x = magic(4);
f = #() x; % captures matrix x
x(1) = 1 % modify x
xx = f() % change not reflected here
Compare that to using handle-class types (e.g containers.Map):
x = containers.Map('KeyType','char', 'ValueType','double');
f = #() x; % captures handle-class object x
x('1') = 1; % modify map
keys(x) % changed
keys(f()) % also changed!
f() == x % compare handle equality, evaluates to true
a = 1.3, b = 0.2, c = 30;
parabola = eval(['#(x) ', num2str(a), '*x^2 + ', num2str(b), '*x + ', num2str(c)]);
I would like to write a function like this:
function foo(goo,...)
if( goo is a function of two variables )
% do something
else
% do something else
end
end
Is there any way I can get the number of variables of a inline function (or of an anonymous function?). To make it more clear:
f = inline('x + y')
g = inline('x')
I want to be able to distinguish that f is a function of two variables and g of 1 variable
EDIT
After I answered this, a better strategy has been found: Just use nargin; see #k-messaoudi's answer.
For inline functions:
According to inline's help:
INLINE(EXPR) constructs an inline function object from the MATLAB expression contained in the string EXPR. The input arguments are automatically determined by searching EXPR
for variable names (see SYMVAR).
Therefore: call symvar and see how many elements it returns:
>> f = inline('x + y');
>> g = inline('x');
>> numel(symvar(f))
ans =
2
>> numel(symvar(g))
ans =
1
For anonymous functions:
First use functions to get information about the anonymous function:
>> f = #(x,y,z) x+y+z;
>> info = functions(f)
info =
function: '#(x,y,z)x+y+z'
type: 'anonymous'
file: ''
workspace: {[1x1 struct]}
Now, again use symvar on info.function:
>> numel(symvar(info.function))
ans =
3
define your variables : syms x1 x2 x3 .... xn;
define your function : f = inline(x1 + x2 + sin(x3) + ... );
number of input argument : n_arg = nargin(f)
number of output argument : n_arg = nargout(f)
I want to create a matrix of functions, however I'd like to dynamically generate it. For example:
myMatrix = zeros(3);
test = #(x) x*y;
for ii = 1:3
myMatrix(ii) = test(ii);
end
something like that to generate: #(y) [y, 2*y, 3*y]
I do not have access to the sym library.
You can't make a matrix of functions, but you can make cell of function handles, e.g.
cellOfFunctions = {};
for i = 1:3
cellOfFunctions{end + 1} = #(y) y*i;
end
Then you can get each handle as follows (for the first function handle):
fh1 = cellOfFunctions{1};
Then execute it with y = 3:
result = fh1(3);
Depending on your purposes, you can make a single function which generates the matrix you have in your example:
>> f = #(y) bsxfun(#times, 1:3, y(:));
>> f(2:5)
ans =
2 4 6
3 6 9
4 8 12
5 10 15