Argument validation and config file

4 次查看(过去 30 天)
Martin Hock
Martin Hock 2022-3-22
回答: Ravi 2023-12-21
We've written a little tool andsome options can be stored in a config file.
So for options, they can be read from the config file or handed over manually as name/value-pairs, and we also have defaults defined in the argument validation.
At this point, the config file takes priority over default and manual input, because it is read after the argument validation, and we cannot differentiate between manual inputs and defaults after the validation.
I'll add some code to show what the issue is.
function math(numbers, options)
arguments
numbers (1,1) {mustBeNumeric} = [1,1]
options.basic (1,:) {mustBeText} = 'add'
end
% At this point I don't know, whether options.basic is from argument or default
% test for config file
if exist('config.json')
configfromfile = jsondecode('config.json');
if isfield(configfromfile,basic)
options.basic = configfromfile.basic;
end % Overwriting with config file.
end
% do maths here
switch basic
case 'add'
add(numbers)
end
end
So at the moment the priority is config file > argument > default
But obviously we'd want to have a "user defined default" in the config file, and possible adjustments via argument: argument > config file > default.
The only way I can think of doing this is by using a wrapper, that is already testing the config file and reading its values, and compiling options for the inner function.
function math(numbers, options)
% test for config file
if exist('config.json')
configfromfile = jsondecode('config.json');
for i=fieldnames(configfromfile)
if ~isfield(options.(i)) % manual input gets priority
options.(i)=configfromfile.(i)
end
end
end
realmath(numbers, options)
end
function realmath(numbers, options)
arguments
numbers (1,1) {mustBeNumeric} = [1,1]
options.basic (1,:) {mustBeText} = 'add'
end
% do maths here
switch basic
case 'add'
add(numbers)
end
end
So what would be the elegant way to handle this?

回答(1 个)

Ravi
Ravi 2023-12-21
Hi Martin Hock,
Please find an approach for prioritizing the inputs in the order arguments > config > default.
function math(numbers, options)
% Define the default options
defaultOptions = struct('basic', 'add');
% If a config file exists, read it and merge with default options
if exist('config.json')
configOptions = jsondecode(configFile);
optionsFromConfig = mergeOptions(defaultOptions, configOptions);
else
optionsFromConfig = defaultOptions;
end
% If options are provided manually, merge them with options from config
finalOptions = mergeOptions(optionsFromConfig, options);
% Do the math operation based on the final options
switch finalOptions.basic
case 'add'
% Call the add function with the provided numbers
result = add(numbers);
end
end
function mergedOptions = mergeOptions(defaults, overrides)
% Merge two structures, where fields in 'overrides' take precedence
mergedOptions = defaults;
overrideFields = fieldnames(overrides);
for i = 1:numel(overrideFields)
mergedOptions.(overrideFields{i}) = overrides.(overrideFields{i});
end
end
We create a variable “defaultOptions” to store the defaults. We check for the “config.json” file and if it exists we merge the options with the already created “defaultOptions”. In this situation, the “config.json” gets priority over “defaultOptions” and if any variable present in “config.json” is already present in “defaultOptions”, then it gets overridden.
Next, we create a variable, “finalOptions” that combines the options from config file, default options, and passed arguments.
The “mergeOptions” function takes two arguments; second one takes higher priority over the other. The variables are overridden with the second argument.
Hope this helps.
Thanks,
Ravi Chandra

类别

Help CenterFile Exchange 中查找有关 Interactive Control and Callbacks 的更多信息

产品


版本

R2021b

Community Treasure Hunt

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

Start Hunting!

Translated by