Structures with multiple, conntected anonymous functions
Show older comments
I have a rather complicated workflow, however, I am having trouble identifying a way for it to work.
I start with a json of the form:
{
"x":3,
"y":6,
"fx":"@(a) a^2+y",
"fy":"@(a,b) y*fy(b)+b*x"
}
This gets read in and evaluated such that:
S.x = 3
S.y = 6
S.fx = @(a) a^2+y
S.fy = @(a,b) y*f(b)+b*x
I have tried both eval and str2funct to create the anonymous function.
Later in the workflow, this structure gets packaged into another structure
dS.S = S;
This is to help with passing a model around between functions.
The problem is, that later on, this command will give an error:
dS.S.fy(1,1)
The error states that the function fx cannot be found. However,
dS.S.fx(1)
does work, WITHOUT there being an "y" defined in the workspace.
Can anyone shed some light on this?
3 Comments
James Tursa
on 13 May 2020
Are the x and y in your function handles supposed to pick of S.x and S.y at the time of evaluation?
Ameer Hamza
on 13 May 2020
What is f(b) in this line
y*f(b)+b*x
is it supposed to be fx(b)?
Kyle Johnson
on 13 May 2020
Accepted Answer
More Answers (1)
the cyclist
on 13 May 2020
Are you sure that y didn't exist in the workspace when you defined the structures? Because in a fresh workspace,
S.x = 3
S.y = 6
S.fx = @(a) a^2+y
S.fy = @(a,b) y*f(b)+b*x
dS.S = S
dS.S.fx(1)
gives the error
Unrecognized function or variable 'y'.
Error in @(a)a^2+y
Does that shed light?
9 Comments
Kyle Johnson
on 13 May 2020
Edited: Kyle Johnson
on 13 May 2020
James Tursa
on 13 May 2020
Edited: James Tursa
on 13 May 2020
The error is because there is no fx function. There is an S.fx function, and a dS.S.fx function, but there is no fx function. When you call dS.S.fy and it goes looking for fx ... it isn't there.
You need to build S differently so that S.fy actually points to the fx function handle you want it to (S.fx). Currently the fx in S.fy is not pointing to anything, so when it is invoked it looks for such a variable or function in the workspace etc.
E.g., you could build the function handles in the workspace first and then attach them to the struct S.
Kyle Johnson
on 13 May 2020
the cyclist
on 13 May 2020
Agreed that it's interesting. Given James' reasoning, I might have expected this analogous statement to be true:
"There is an S.y variable, and a dS.S.y variable, but there is no y variable. When you call dS.S.fx and it goes looking for y ... it isn't there."
If you used the debugger to step into dS.S.fy before it evaluates, you'll see the workspace of the anonymous function looks like this:

So, y is there, but fx is not. I frankly don't fully understand it, but my guess is that this is because S.y can be evaluated, but S.fx cannot be (without further input).
The closest I could get to the spirit of what you were trying to do is
x = 3;
y = 6;
S.x = 3;
S.y = 6;
S.fx = @(a) a^2+y;
S.fy = @(a,b,fx) y*fx(b)+b*x;
dS.S = S;
dS.S.fx(1)
dS.S.fy(1,1,dS.S.fx)
Kyle Johnson
on 13 May 2020
James Tursa
on 13 May 2020
Edited: James Tursa
on 13 May 2020
Function handles take snapshots of everything in the workspace that is part of them at the time they are built. It doesn't matter if you subsequently change those variables or even clear them downstream in your code because the function handle has stored inside of it those snapshots. The only way to change those snapshots is to rebuild the function handle from scratch. E.g.,
>> a = 4;
>> b = 5;
>> fx = @(x)a*x+b; %<-- fx stores snapshots of a and b inside itself
>> fx(2)
ans =
13
>> a = 6; % <-- this changes a, but does not change the snapshot of a inside fx
>> b = 7; % <-- this changes b, but does not change the snapshot of b inside fx
>> fx(2)
ans =
13
And then suppose we create a new function handle fy:
>> fy = @(x,y) fx(x)+a % <-- fy stores current snapshots of fx and a
fy =
function_handle with value:
@(x,y)fx(x)+a
>> fy(2,3)
ans =
19
Now change fx:
>> fx = @(x)b*x+a % <-- fx stores current snapshots of a and b
fx =
function_handle with value:
@(x)b*x+a
>> fy(2,3)
ans =
19
Notice that fy didn't change. That is because fy is working with it's shapshot of fx as fx existed at the time that fy was created. It doesn't matter that you subsequently changed fx downstream in your code.
You could do this to get fx defined properly in fy:
x =3;
y = 6;
S.x = x
S.y = y
fx = @(a) a^2+y % <-- fx stores shapshot of y
fy = @(a,b) y*fx(b)+b*x % <-- fy stores snapshots of fx and x and y
S.fx = fx
S.fy = fy
BOTTOM LINE: Function handles always work with shapshots of workspace variables at the time of their creation. If you want different behavior, use actual function files that will go looking for functions in realtime instead of using function handles.
Kyle Johnson
on 13 May 2020
James Tursa
on 13 May 2020
Yes, it appears you understand how function handles work now. Your current approach seems correct to me.
Kyle Johnson
on 13 May 2020
Categories
Find more on Workspace Variables and MAT Files in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!