What is the recommended way to pass long list of parameters between main workspace and function?
27 vues (au cours des 30 derniers jours)
Afficher commentaires plus anciens
In my work I encountered a problem with passing variables betwen main script and function. Of course I can do it manually:
a1=1;a2=2;a3=3;a4=4;a5=5; %The list is much longer in my project, here just example
sum=calcvalues(a1,a2,a3,a4,a5);
function sum=calcvalues(a1,a2,a3,a4,a5)
sum=0;
b=[1,2,3];
for i=1:3
sum_tmp=sum_support(a1,a2,a3,a4,a5,b(i));
sum=sum+sum_tmp;
end
end
function sum_support = sum_support(a1,a2,a3,a4,a5,b)
sum_support=a1*a2+a3^b+a4*a5;
end
But I have to retype all values every time, and after any modification in list of function inputs there is no option to sync with other executions. Additionally, the list is very long, and take space in every function, making the code less readable. My intention was to override this with
function sum=calcvalues(varargin)
But this doesn't preserve file names. The output is just a 1x5 cell with anonymouse numbers. So far I managed to use eval to assign names dyanmicaly but this does not looks like a good practise. What is the recommended way to restore/preserve the names?
EDIT to clarify:
Here is the closest solution to what I expected. However this requires to use save command to unpack the structure. Is it possible to do this in more elegant way?
a1=1;a2=2;a3=3;a4=4;a5=5; %The list is much longer in my project, here just example
value_holder=struct('a1',a1,'a2',a2,'a3',a3,'a4',a4,'a5',a5);
sum=calcvalues(value_holder)
function sum=calcvalues(value_holder)
sum=0;
b=[1,2,3];
for i=1:3
sum_tmp=sum_support(value_holder,b(i));
sum=sum+sum_tmp;
end
end
function sum_support = sum_support(value_holder,b)
save('temp.mat','-struct','value_holder')
load('temp.mat')
sum_support=a1*a2+a3^b+a4*a5;
end
7 commentaires
Réponse acceptée
dpb
le 24 Mai 2022
If the variables are such as your example of a sequence of number variables with same root name, that implies they're related/same thing, just different instances. In that case I'd use an array and indexing -- "A" instead.
Alternatively, if they are actually different variables, take those that are related and create a structure to pass for succinctness and then reference the component variables in the struct.
Alternatively, if there are a lot of disparate variables, consider putting them into a table and pass the table.
Would need a lot more information about the actual variables and their use to have specifics, but design the data structure around the problem and then implement it, don't just create variables willy-nilly with no overall structure.
10 commentaires
Matt J
le 24 Mai 2022
Modifié(e) : Matt J
le 24 Mai 2022
Alright, I'm mentioning this against my better judgement, but you can unpack the variables in the implicit manner that you want by doing,
eval(structvars(s)')
This might be a compromise in performance between load/save and my suggestion. However, eval() has at least the same programming hazards as load(), so take great heed of the discussion here,
Plus de réponses (3)
Steven Lord
le 24 Mai 2022
If all your variables are related and so should remain together, I would pack them into a struct array.
s = struct('a1',1,'a2',2)
s.a3 = 3;
s.a4 = 4;
s.a5 = 5
Now you can pass s into and out of your function and use the values in its fields in your function. Functions that need some but not all of the fields in the struct can ignore the ones they don't need, and you can add fields to the struct without affecting existing code.
3 commentaires
Steven Lord
le 24 Mai 2022
Unpack just the variables that ODE function needs at the top of the ODE function. Or if a variable only appears once in the ODE function, you can index into the struct rather than creating an additional variable.
s = struct('a1',1,'a2',2,'a3',3,'a4',4, 'a5', 5);
function sum=calcvalues(s)
sum=0;
b=[1,2,3];
for i=1:3
sum_tmp=sum_support(s,b(i));
sum=sum+sum_tmp;
end
end
function sum_support = sum_support(s,b)
% The next few lines were added
a1 = s.a1;
a2 = s.a2;
a3 = s.a3;
a4 = s.a4;
% a5 = s.a5; % Instead of doing this you can use s.a5
sum_support=a1*a2+a3^b+a4*s.a5; % like I did here
end
dpb
le 25 Mai 2022
Modifié(e) : dpb
le 25 Mai 2022
For something that looks likes OP's example of a bunch of constants to retrieve, I think I'd do as you suggest and retrieve in the individual ODE functions the ones needed for the function --
s=struct('coeff',[1:5]); % put all the coefficients in array instead of many (unuseful anyway) names
Then in each ODE function can write something like
IDX=[1,3,4]; % the needed coefficients for this ODE
S=sum_support(s,IDX); % call the function with needed index array
function sum_support = sum_support(s,b)
sum_support=sum(s.coeff(b))
end
At command line to show syntax works as expected...
>> s = struct('coeff',[1:5]);
>> IDX=[1 3];
>> sum(s.coeff(IDX))
ans =
4.00
>>
One could make things more simple for using for the ODE functions by creating either a struct array of an element of the coefficients for the given ODE and even have a name to ensure use right array element or if it's not too complicated, use a 2D array where each row contains the coefficents for the given ODE so the very long 1D string is given some structure associated with its use.
The disadvantage is that they are then position dependent so Steven's solution is better in that regards.
Matt J
le 24 Mai 2022
Modifié(e) : Matt J
le 24 Mai 2022
In the case of your posted example, the appropriate re-implementation would be,
a=1:5;
result=calcvalues(a);
function accum=calcvalues(a)
accum=0;
b=[1,2,3];
for i=1:3
accum=accum+sum_support(a,b(i));
end
end
function sum_support = sum_support(a,b)
sum_support=a(1)*a(2)+a(3)^b+a(4)*a(5);
end
6 commentaires
Matt J
le 24 Mai 2022
Modifié(e) : Matt J
le 24 Mai 2022
I said "if" they are, not that I know that for a fact. If they aren't the same length, you can still possibly use a cell array.
The point though is that you should go through your variables to see which ones are similar in size and type, and which can be grouped into arrays.
Catalytic
le 24 Mai 2022
Modifié(e) : Catalytic
le 24 Mai 2022
Do not use load/save to introduce undeclared variables in your workspace. This can have unexpected effects as described in this doc page -
which also mentions recommended alternatives.
5 commentaires
Catalytic
le 24 Mai 2022
The fact that you have a million different variables in your calculation means that the code will already be unreadable. Like the other contributors, I wonder if your variables could be better aggregated into vectors, matrices, and other array types. The MAT in MATLAB stands for matrix, and you should be using them.
Voir également
Catégories
En savoir plus sur Logical 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!