2
function y = myfunc(param)
C = param.C;
L = param.L;
Kp = param.Kp;
Ki = param.Ki;
...

Is there a way to generalize the above code? I know how to generalize the structure access using fieldnames() and getfield(), but not how to set variables without calling eval() (which is evil).

for n = fieldnames(param)'
  name = n{1};
  value = param.(name);
  do_something_with(name,value);   % ????
Jason S
  • 184,598
  • 164
  • 608
  • 970

4 Answers4

5

never mind, I figured it out; this helper function works:

function vars_pull(s)
    for n = fieldnames(s)'
        name = n{1};
        value = s.(name);
        assignin('caller',name,value);
    end
Jason S
  • 184,598
  • 164
  • 608
  • 970
  • Bonus points for having your FOR loop over the fieldnames directly, rather than extracting the fieldnames and then looping for the length of that cell array :-) – Bob Gilmore Mar 12 '12 at 16:11
2

The only way to create a variable whose name is determined at run-time is to use a function like eval, evalin, feval, or assignin. (assignin is the least evil choice BTW, at least you don't need to convert your value to a string and back.)

However, I question why you want to do that, why not just access the values through the input structure as you need them. If you want to save typing (speaking from experience, as I am extremely lazy), I usually name my input parameter structure something short, like p. The throughout my code I just access the fields directly, (e.g. p.Kp, and after a while I don't even see the p. anymore.) This also makes it easy to pass the structure into subfunctions as needed.

Pursuit
  • 12,285
  • 1
  • 25
  • 41
  • Aside from laziness/clarity, I'm calling Simulink with the `sim()` command, on a model with a bunch of gain blocks and other parameters that are accessed from the workspace. – Jason S Mar 12 '12 at 15:42
  • Yep. For that Simulink interface that is what you need to do, and your self-answer is the way to do it. (That workspace variables are just sneaky globals is a long time frustration of mine, but not relevant here.) – Pursuit Mar 12 '12 at 18:04
  • I want to use this for a struct coming from inputParser which has been validated, but I want the values to wind up in the properties of the class I'm creating. So why not access from the input structure? Because that'll break the public API I'm creating and I explicitly don't want to expose that implementation detail to callers. – lamont Aug 17 '19 at 22:14
1

You can use the excellent submission at FileExchange:

V2STRUCT - Pack & Unpack variables to & from structures with enhanced functionality

yuk
  • 19,098
  • 13
  • 68
  • 99
0

Here's a workaround: save the structure to a .mat file using the '-struct' option, and then immediately reload it. Here's an example for struct variable X:

save('deleteme.mat','-struct','X');
load('deleteme.mat');
delete('deleteme.mat');

It's kludgey, but actually pretty fast, at least with an SSD.