Saving function variables without evil eval

4 Ansichten (letzte 30 Tage)
Remco1988
Remco1988 am 29 Nov. 2016
Kommentiert: Bardo Mueller am 22 Jul. 2021
Note: I am aware that using eval is usually not a good practice. However for me it is very difficult to understand when it can be used and when not.
Question: So my question is, is this a proper usage? and if not how should I do it differently?
Background: I have a function that occasionally crashes (not going in to detail in this question) As it is run after 30 minutes of simulation I want to avoid re-running the simulation. So I though of a checkpoint at the start of the function in which all variables are saved, in case it fails.
Code: I start of saving all variables to base workspace (could be a .mat file if thats prefered)
function test(var1, var2, var3, var4, ....)
.
.
.
%Temporary store results to workspace
variables = who;
for ii = 1:length(variables);
insurance.(variables{ii}) = eval(variables{ii});
end
assignin('base','insurance',insurance)
For convenience I saved all variables in to a single struct, but even if I saved them seperatly, I cannot think of a way to avoid eval in this situation.
Code part 2: The user now can (try) to re-run by calling the function "test(insurance)", which will restore the saved variables
function test(var1, var2, var3, var4, ....)
% load temporary stored results to m-file
if nargin == 1
insurance = var1;
names = fieldnames(insurance);
for ii = 1:length(names)
feval(@()assignin('caller',names{ii},insurance.(names{ii})))
end
end
  2 Kommentare
Remco1988
Remco1988 am 29 Nov. 2016
now that I think of it at home, might be much better to change the entire function to a varargin input? in that way I do not need to rewrite everything twice to save/load variables.
function test(varargin)
% load temporary stored results to m-file
if nargin == 1
varargin = varargin{1} % rewrite varargin to default input order
end
%Temporary store results to mat-file
save(fname,varargin) % saves 1xN cell to mat file
var1 = varargin{1};
var2 = varargin{2};
....
less readable, but better I guess
Bardo Mueller
Bardo Mueller am 22 Jul. 2021
should be
save(fname, 'varargin')

Melden Sie sich an, um zu kommentieren.

Antworten (3)

dpb
dpb am 29 Nov. 2016
Just save then load will do all automagically...see
doc save % for details
  2 Kommentare
Remco1988
Remco1988 am 29 Nov. 2016
i could use save and load "insurance" instead of assigning to the base workspace, but this does not resolve my 'eval' part of the code.
dpb
dpb am 29 Nov. 2016
Bearbeitet: dpb am 29 Nov. 2016
Why? What do you need eval for if you just save and restore the variables as they were? Don't see the issue, sorry...
function YourRescueFunction(insurance)
load insurance
results=TheOriginalFunction(variablesFromInsuranceReloaded);
Actually, if you were to wrap the above around the initial and make it a nested function within the recovery routine, then everything in it is also local within the original and you don't even have an issue of workspace at all it would seem...

Melden Sie sich an, um zu kommentieren.


Jan
Jan am 29 Nov. 2016
Use a function and not scripts, which pollute the base workspace with variables. Then you can use save to store all current variables, but not any other stuff of the base workspace. But even if you use save in scripts: There is no need for eval at all.

Alexandra Harkai
Alexandra Harkai am 29 Nov. 2016
Bearbeitet: Alexandra Harkai am 29 Nov. 2016
How about having all these state variables in a struct in the first place? Then you can save them to a mat file, for example:
var_struct.var1 = <some_value>;
var_struct.var2 = <some_other_value>;
...
fname = [datestr(now,'yymmdd_HHMMSS'), '.mat'];
save(fname, '-struct', 'var_struct', '-v7.3');
  1 Kommentar
Remco1988
Remco1988 am 29 Nov. 2016
Bearbeitet: Remco1988 am 29 Nov. 2016
It is a possibility, but would you suggest either creating a struct within the function from the different inputs:
test(var1, var2, var3, var4, ....)
if nargin == 1 % user running struct
var_struct = var1;
var1 = var_struct.var1;
var2 = var_struct.var2;
...
else
var_struct.var1 = var1;
var_struct.var2 = var2;
...
save(fname, var_struct) % make checkpoint
end
or have a function that only allows a single struct input in the first place:
save(fname, var_struct)
test(var_struct) % run function
.
test(var_struct)
var1 = var_struct.var1;
var2 = var_struct.var2;
....
the first one is clunky with a lot of inputs (thats why I created a for loop). The 2nd one is more elegant, but I don't think functions with a struct input are good practice either?

Melden Sie sich an, um zu kommentieren.

Community Treasure Hunt

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

Start Hunting!

Translated by