I have a function for which I would like to pass in arguments via varargin
, and use the inputParser
to ensure the inputs are sane. Some arguments are required, and some are not. Here is an example:
function myFunc(varargin)
p = inputParser;
p.addRequired(...
'numStates', ...
@(x) validateattributes(x, {'numeric'}, ...
{'scalar', 'integer', 'positive'}));
p.addRequired(...
'numInps', ...
@(x) validateattributes(x, {'numeric'}, ...
{'scalar', 'integer', 'positive'}));
p.addRequired(...
'numOuts', ...
@(x) validateattributes(x, {'numeric'}, ...
{'scalar', 'integer', 'positive'}));
p.addRequired(...
'X0', ...
@(x) validateattributes(x, {'numeric'}, ...
{'vector'}));
p.addOptional(...
'freq', 10, ...
@(x) validateattributes(x, {'numeric'}, ...
{'scalar', 'integer', 'positive'}));
p.addOptional(...
'SimulinkVariables', struct(), ...
@(x) isa(x, 'struct'));
p.parse(varargin{:});
%# do stuff with variables
end
I would like to be able to pass in arguments as follows; it should not matter which pair gets passed in when, as long as the required ones are there. So a sample call might be:
myFunc('numStates', 4, 'numInps', 2, 'numOUts', 3, 'X0', [4;0]);
Apparently, this syntax is illegal; parse()
expects that the first arguments in it are the required values, but they should not be explicitly named, i.e., as in:
function myFunc(numStates, numInps, numOuts, X0, varargin)
...
p.parse(numStates, numInps, numOuts, X0, varargin{:});
end
Is there a simple way to make this do what I want, i.e., the first function? I guess the easiest thing to do is do something to reorder the elements of varargin
and kick out the argument names, but that isn't terribly elegant.
The most elegant solution I can think of is to subclass inputParser
. So you could do something like this (save as myInputParser.m):
classdef myInputParser < inputParser
properties
required = {};
end
methods
function obj = myInputParser
obj = obj@inputParser;
end
function addRequired(obj, argname, validator)
obj.required = {obj.required{:}, argname};
obj.addOptional(argname, [], validator);
end
function parse(obj, varargin)
params_input = varargin(1:2:end);
for i=1:length(obj.required)
if isempty(strmatch(obj.required{i}, params_input))
error(sprintf('Required named parameter %s was not passed to function', obj.required{i}));
end
end
parse@inputParser(obj, varargin{:});
end
end
end
Then change
p = inputParser;
to
p = myInputParser;
and then your code will work as you want it to.
Note that this might not handle all edge cases correctly, and I haven't tested it extensively, but it does work with your example use case.
In InputParser you can add ParameterName - ParameterValue pairs only with addParamValue
. Those arguments are supposed to be optional.
As a workaround you can add all your parameters with addParamValue
and use []
as default value for required arguments.
Then you can do one of the following:
validateattributes
function for required arguments (however in this case the error message will not say this is required arguments, but that it has to be non-empty) if
or assert
) that required arguments should be not-empty with your own error message.You are not limited to use []
. The default can be any value not appropriate for a particular parameter and easy to check.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With