I need something similar to evalin
, but original evalin
of Matlab cannot be used recursively. For example, I have function f0 which calls 2 other functions f11 and f12:
function f0()
[v1, v2] = deal(1, 1);
f11();
f12();
disp(v1);
end
Functions f11 and f12 use variable v1, and both call function f2:
function f11()
v1 = evalin('caller', 'v1');
f2();
assignin('caller', 'v1', v1);
end
function f12()
v1 = evalin('caller', 'v1');
f2();
assignin('caller', 'v1', v1);
end
And the function f2 should use both variables v1 and v2 of f0's workspace:
function f2()
v1 = evalin('caller', 'v1'); % get variable v1 from f11 or f12
% since there is already a variable v1
% in f11 and f12's workspaces
% TODO: get v2 from f0
if v2 == 1
v1 = v1 + 1;
end
assignin('caller', 'v1', v1);
end
Is there anyway to make the TODO possible without using v2 = evalin('caller', 'v2')
in f11 and f12 ?
This is possibly one of the worst way of organising your data transfer between functions. Workspaces of functions are separated for a good reason, to keep things clean and organised.
You are trying to bypass all safeguards put in place by people who designed this language (and many other language who share this separation of workspace/scope). These "bypass" functions are available in Matlab for punctual usage when you are prototyping. They are not intended for heavy usage or for final solution (most of them won't be compilable actually).
It is
You say in the comment that passing variable as parameter is complicated because of their number, but every time you call something like
x = evalin('caller', 'x');
you have to write 1 full line of code to retrieve your value anyway. And thenassignin('caller', 'x', x);
is another line of code to send it back ... that's madness.Would it not be simpler (and shorter) to just have
x
in your function input parameters ?? (it is still faster to have 100 variables in input than to have 200 full lines of codes to retrieve then resend these values from uncertain locations).Recommended (if practical): pass variable in parameter
To make variable passing easy you could for example gather them all in a
structure
(or acell array
):And then
And so on, as long as you pass the variable to the next function, then retrieve it in output, this would work with any level of recursion.
Recommended (if above not possible): Use nested functions
If you define your function
f11()
inside yourf0()
, the variable which have the same name in the 2 functions will be shared (visible by at both levels). Read thedocumentation
for more detail. This way you would not need your numerous call toevalin/assignin
because the variable is know everywhere. Your function would have to be written in this form:Stack Exchange does not render that, but in the Matlab editor you could notice that the "shared" variable will be highlighted in a different colour (to alert you that they have a different scope than standard variable).
If I run
f0()
I do get:Which was the expected result. The only downside, as you can see, is that if you are calling
f2()
from withinf11()
andf12()
, the functionf2()
has to be written within each of them (so a bit of copy/paste). Unless at this level of recursion you do not have too many variable to pass so you could consider writingf2()
on the side and using the standard variable passing scheme.Can work, but not recommended
Now if you are still keen on writing numerous lines of codes just to pass single variables around, there are still 2 options:
global
variablessetappdata
andgetappdata
I do not like to use
global
so I won't detail here. Just remember that for a variable to be reallyglobal
it has to be declared asglobal
in every function where it is used.For the
appdata
method, you need a "container" which will be accessible to all your functions. You can use the "root" object for that (identifier:0
).So for example, when you want to store a variable you could use:
then in any of your function, get the value, work on it then store it back:
Apply the same principle in your base function and
f11()
,f12()
, etc ... Just remember to always store any value back after you modified it so it is available for the next function which will need it.You can save
f0()
's variables to a file and then call aload
method inf2()
to import those variables inf2()
workspace.Just trying to get this right: Your 'Variables' are holding a value that should be consistent over operations that you like to perform on them. Only a shot in the dark, but have you tried Object-Orientation on your problem.
Depending on your specific problem this might be the easiest way to get recursion right. OO in Matlab isnt that hard to learn.
Hth