Best practice for updating default parameter values inside a function, preferably with struct

26 vues (au cours des 30 derniers jours)
I apologize if this question has been asked in some form or another. Feel free to point me to any existing answers...
My use case is fairly straightforward:
I have a simulation which has many different parameters. I have packaged my simulation into a function, which contains default values for these parameters. However, I would like to be able to call my simulation function, and pass in an input to override any one or all of my default parameter values. Since there are a large number of parameters, I would find it convenient to pass in the input as a structure.
So say for example:
function output = mySim(inputStruct)
%Assign defaults:
x0 = 1;
y0 = 2;
z0 = 3;
vx0 = 0;
vy0 = 0;
vz0 = 1;
dt = 0.1;
% Desired update code....
%-> check if inputStruct exists
%-> update any of the parameters with the value contained in inputStruct
output.x = x0+vx0*dt;
output.y = y0+vy0*dt
output.z = y0+vz0*dt
end
I can think of any number of, and probably dumb, ways to do this. One such way is a helper function I wrote, which will read through a struct and load all the fields as variables into the local workspace. Here it is pasted below for reference:
function load_struct_vars(inp)
% Extracts fields from structure and creates new variable with that
% fieldname and value in the calling workspace.
names=fieldnames(inp);
values=struct2cell(inp);
for i=1:length(names)
assignin('caller',names{i},values{i});
end
end
This achieves the desired result of overwriting the default values with the new ones from the struct, and also gives me the convenience of not having to make any corresponding edits to the update code. I.e., if I create additional default parameters in my simulation function, I can override these values simply by adding the new var as a field in my input struct.
My solution however, relies on the assignin() function, which I have learned is a really bad idea, and not good practice. I have noticed myself that it is really slow as well.
Hence my question: what is a recommended best practice for achieving the result I have outlined?
Thanks in advance!

Réponse acceptée

TADA
TADA le 31 Déc 2019
Modifié(e) : TADA le 31 Déc 2019
Using assignin as your configuration strategy is a bad idea not only due to bad performance. It's also very prone to bugs. lets say you have a typo when you try to spell the local variable, this code will still work but the value will remain unchanged. This scenario can easily take several hours to debug. Another example is if you have some local variable you don't want to be messed with from outside. Then bam, another half a day debugging. You can achieve similar functionality with better performance and more robustness by using a local config struct where you will keep all thelocal variables that can be overridden by the caller like that:
function output = mySim(inputStruct)
%Assign defaults:
cfg.x0 = 1;
cfg.y0 = 2;
cfg.z0 = 3;
% copy values from input struct
if nargin > 0
cfg = load_struct_vars(cfg, inputStruct);
end
% for the sake of this answer let's say
% you don't want to allow the function
% caller to meddle with these variables
vx0 = 0;
vy0 = 0;
vz0 = 1;
dt = 0.1;
output.x = cfg.x0+vx0*dt;
output.y = cfg.y0+vy0*dt;
output.z = cfg.y0+vz0*dt;
end
function cfg = load_struct_vars(cfg, vars)
varFirlds = fieldnames(vars);
for i = 1:numel(varFields)
fld = varFields{i};
if isfield(cfg, fld)
cfg.(fld) = vars.(fld);
else
throw(MException('load_struct_vars:invalidVar', 'varriable %s is not a valid varrialbe to set', fld));
end
end
end
That way if you try to inject an invalid variable, it's gonna notify you with a nice exception
And if you want to add some validation I suggest you try to use Matlabs input parser which was made for that purpose exactly

Plus de réponses (0)

Catégories

En savoir plus sur Performance and Memory dans Help Center et File Exchange

Community Treasure Hunt

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

Start Hunting!

Translated by