Mic*_*l A 5 validation matlab function optional-arguments input-parameters
I have a MATLAB file that contains a single top-level function, called sandbox
. That function in turn contains two nested functions, mysum
and myprod
, which are identical in functionality and what parameters they allow except that one uses @sum
internally and the other uses @prod
internally. My goal is to create a wrapper function to use in both mysum
and myprod
that takes care of all the validation and input parsing. This function is called applyFunc
.
Here's where it gets tricky. mysum
and myprod
come in two forms:
mysum(v)
returns sum(v, 1)
. mysum(v, 'imag')
returns sum(v, 1) + 1i
Any other combinations of input should throw an error.
I'm having trouble using inputParser
to parse these various combinations of input, specifically the optional string input. Here's the code:
function sandbox()
%% Data
v = [1 4; 3 3];
%% Calculations
s = mysum(v);
si = mysum(v, 'imag');
p = myprod(v);
pi = myprod(v, 'imag');
%% Accuracy tests
assert(isequal(s, [4 7]))
assert(isequal(si, [4+1i 7+1i]))
assert(isequal(p, [3 12]))
assert(isequal(pi, [3+1i 12+1i]))
function x = mysum(varargin)
x = applyFunc(@sum, varargin{:});
end
function x = myprod(varargin)
x = applyFunc(@prod, varargin{:});
end
end
function x = applyFunc(func, varargin)
p = inputParser();
p.addRequired('func', @(x) validateattributes(x, {'function_handle'}, {'scalar'}));
p.addRequired('v', @(x) validateattributes(x, {'double'}, {}, 'applyFunc:msg', 'v'));
p.addOptional('imag', '', @(x) validatestring(x, {'imag', ''})); % THIS LINE IS THE PROBLEM
p.parse(func, varargin{:});
f = p.Results.func;
v = p.Results.v;
strflag = p.Results.imag;
x = f(v);
if ~isempty(strflag)
validatestring(strflag, {'imag'});
x = x + 1i;
end
end
Run Code Online (Sandbox Code Playgroud)
The line that's causing the problem is this one (as marked in the code above):
p.addOptional('imag', '', @(x) validatestring(x, {'imag', ''}));
Run Code Online (Sandbox Code Playgroud)
The documentation for inputParser says that:
For optional string inputs, specify a validation function. Without a validation function, the input parser interprets valid string inputs as invalid parameter names and throws an error.
Unfortunately I don't have any idea how to do this. Is there something simple Im missing or what? If the 'imag'
argument isn't passed at all (as in the assignment of s
and p
), the code works fine, but if I do pass it, I get this error:
Error using sandbox>applyFunc (line 32)
The value of 'imag' is invalid. It must satisfy the function:
@(x)validatestring(x,{'imag',''}).
Error in sandbox/mysum (line 18)
x = applyFunc(@sum, varargin{:});
Error in sandbox (line 7)
si = mysum(v, 'imag');
Run Code Online (Sandbox Code Playgroud)
Any help?
The problem is that validatestring
returns the matching string from the cell argument ({'imag',''}
) rather than a Boolean indicating if it passes validation. Instead, use strcmp
and any
:
@(x) any(strcmp(x,{'imag', ''}))
Run Code Online (Sandbox Code Playgroud)
Also, with validatestring
, if the input string did not match either 'imag'
or ''
(actually just 'imag'
since empty strings only match in R2014a+), it would throw an error rather than returning false so that the inputParser
could return the appropriate error.
解决该问题的另一个好方法是applyFunc
完全更改语法,以便将Parameter-Value with作为参数并使用经过验证的布尔值作为输入,而不是'imag'
作为可选的字符串输入参数。'imag'
Amro 在评论中建议的输入定义:
p.addParameter('imag', false, @(x)validateattributes(x, {'logical'}, {'scalar'}))
Run Code Online (Sandbox Code Playgroud)
用法:
mysum(x,'imag',true)
mysum(x) % default is equivalent to mysum(x,'imag',false)
Run Code Online (Sandbox Code Playgroud)
这将p.Result.imag
通过logical
标量简化其余代码。我会建议:
x = f(v) + p.Result.imag*1i;
Run Code Online (Sandbox Code Playgroud)