Clean way of integrating argument-handling with old code (struct vs. key-val pair with "arguments" keyword)

38 views (last 30 days)
Our existing analysis pipeline (pre-R2019b) often configures options for various functions by passing a struct whose field names are the names of the options (those fields then holding the value for that option). This would be followed-up by a series of if(~isfield( commands to set the default cases, so something like this:
function myfunc(main_arg,optional_arg_struct)
if(~isfield(optional_arg_struct,'option1'))
optional_arg_struct.option1 = 'some_default';
end
...
We've recently moved our pipeline to a newer version of Matlab, so I'd like to make use of the arguments feature introduced in R2019b in writing my new functions, but have them be backwards-compatible with options passed in our "old" way. If I pass such a struct to a function using the arguments keyword, rather than key-value pairs, I get
Error using myfunc (line 1)
Invalid argument at position 2. Function requires exactly 1 positional input(s).
A workaround I've found is to provide three arguments, where the second is our old-style optional_arg_struct and the third is the arguments-style set of key/value pairs. In the arguments block, I basically ignore optional_arg_struct (just pass it as-is) and then have to manually jam the two of them together after the conclusion of the arguments block. But this is so clunky as to completely subvert the benefit of using the arguments functionality. Some extra conditionals/parsing prior to the arguments block could also achieve what I want, but it seems that the arguments syntax doesn't support that.
Is there any (clean) way of achieving what I want?

Accepted Answer

Jacob Mathew
Jacob Mathew on 1 Apr 2024 at 3:33
Going through your query, it is difficult to reproduce the error without reference to the code that you are using in your new approach.
Meanwhile, a possible workaround that would be to use “varargin” and check if the first variable parameter is a struct or a string. Based on that you can decide to go with the older or newer workflow. An example of this is below:
function func(main_arg,varargin)
arguments
main_arg % main_arg conditions & validation can done here
end
arguments(Repeating)
varargin
end
if(isstruct(varargin{1}))
% you have passed a struct as the first optional argument
% Assuming that all key value pairs are within the struct,
% check for the missing keys and add their default values below
optional_arg_struct = varargin{1};
if(~isfield(optional_arg_struct,'option1'))
optional_arg_struct.option1 = 'some_default';
end
else
% you did not pass a struct, which means there are going to be name
% value pairs within the varargin. You can read those using a loop
% as follows
defaultStruct = struct('option1','some_default');
if mod(length(varargin), 2) ~= 0
error('Parameters should be in key-value pairs');
end
for k = 1:2:length(varargin)
% If the varargin contains a field, then we replace the structs
% default value with the one passed in the varargin
if isfield(defaultStruct, varargin{k})
defaultStruct.(param) = varargin{k + 1};
else
error('Unknown parameter name: %s', varargin{k});
end
end
end
end

More Answers (0)

Categories

Find more on Structures in Help Center and File Exchange

Products


Release

R2021a

Community Treasure Hunt

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

Start Hunting!