inputParser验证参数未按预期执行

时间:2016-08-15 19:21:44

标签: matlab validation parsing

我写了一个测试函数,并遇到了inputParser

的问题
function doit(varargin)
p = inputParser;
p.KeepUnmatched = 1;
% why does this bomb if I put in @ischar ? 
p.addOptional('shape','forgot',@(x) true);
p.addParameter('color', 'k', @(x) true); % 'cause color could be char or triplet
p.parse(varargin{:});
%  more code using the parsed inputs
end

如果我跑

doit('hello','color','g')

doit('color','g')

使用上面的代码,所有工作都按预期工作。但是,如果我将optional参数的输入验证更改为 p.addOptional('shape', 'forgot',@(x) ischar),我在p.parse(varargin{:})

收到错误消息
No value was given for 'g'. Name-value pair arguments require a name followed by a value.

看起来我不理解最终的参数,即应该验证输入参数的匿名函数。有什么问题?

编辑:

Win7上的Matlab 2015a。

编辑2:变分测试用例

似乎varargin中每个参数的确切类别会影响行为。

function threeout = argthree( varargin)     
p = inputParser; 
p.KeepUnmatched = true; 
%defshape = 'forgot'; 
defshape = 5; 
addOptional(p,'shape',defshape,@isnumeric); 
addParameter(p,'color', 'k',@ischar); % 
parse(p, varargin{:}); 
threeout = p.Results; 
end

至少有两件事可能导致parse()失败。第一:这:

>> argthree('nono','color','vu') 
Error using argthree (line 10) 
No value was given for 'vu'. Name-value pair arguments require a name followed by a value. 

请注意,即使可选的“形状”应该针对数字进行测试,但解析器似乎认为“nono”是名称 - 值对的开头。

Entering either a numer or nothng works: 
>> argthree('color','vu') 
ans = 
color: 'vu' 
shape: 5 
>> argthree(7,'color','vu') 
ans = 
color: 'vu' 
shape: 7

现在替换addOptional行而不进行验证: addOptional(p,'shape',defshape );

为所有三个电话获得与上述相同的结果。

现在将默认值更改为 defshape = 'forgot' % a charstring

>> argthree('nono','color','vu') 
Error using argthree (line 10) 
No value was given for 'vu'. Name-value pair arguments require a name followed by a value. 
>> argthree('color','vu') 
ans = 
color: 'vu' 
shape: 'forgot' 
>> argthree(7,'color','vu') 
ans = 
color: 'vu' 
shape: 7 

现在尝试验证字符串输入:再次替换addOptional行 - addOptional(p,'shape',defshape,@ischar );

>> argthree('nono','color','vu') 
ans = 
color: 'vu' 
shape: 'nono' 
>> argthree('color','vu') 
Error using argthree (line 10) 
No value was given for 'vu'. Name-value pair arguments require a name followed by a value. 
>> argthree(7,'color','vu') 
Error using argthree (line 10) 
The value of 'shape' is invalid. It must satisfy the function: ischar. 

这里有一些非常不一致的parse()尝试将varargin{:}与参数列表(可选或名称 - 值对)匹配的方式。由于发生了不一致的失败,我无法设置一个带有Optional char参数后跟一个名称 - 值对的情况,就我所见。

更新

我在MathWorks上提交了一份错误报告,“技术支持案例#02121531”,他们能够重现这个问题。

3 个答案:

答案 0 :(得分:1)

  

tl; dr 尝试@ischar@(x) ischar(x)代替@(x) ischar

<强>解释

我怀疑错误消息不合适,并且只是由验证函数引发错误导致的一般错误。 Matlab允许两种验证功能:

  • 返回true / false的一个,在这种情况下会生成相应的错误
  • 只是简单地启动并抛出异常,此时解析失败。

我怀疑在后一种情况下,matlab只会喷出一条关于你无法传递适当参数的通用无法提供的错误消息。

我认为您的问题可能是,在您的匿名函数中,您实际上是在没有参数的情况下调用ischar(函数 name ),这会导致错误。这会引发异常,并且matlab会将此解释为您的验证函数抛出异常以表示解析失败。

因此将@(x) ischar替换为@ischar@(x) ischar(x)(它们都是对应于单参数函数的有效函数句柄),它应该有效(假设没有其他错误)。< / p>

答案 1 :(得分:1)

我一直在与MathWorks,技术支持案例#02121531讨论这个问题。

我写了一篇关于我希望做什么的解释:

  

我希望能够有一个可选参数   字符串,然后是一个或多个值 - 参数对   其中的参数是字符串。因为我将“可选”解释为   只是那个,即没有的varargin {:}元素之一   需要存在,我期望以下两个命令   会工作:

     

foop =parseCheck('nono','color','vu');

     

     

foop =parseCheck('color','vu');

     

然而,   解析器函数似乎无法理解“'color'”是一个   值 - 参数对中的值。解析器看到一个字符串   作为第一个varargin并立即将其标识为Optional   参数。我的观点是,这既不直观也不可取。

     

我认为这是一个错误,并建议解析器代码   重写,以便任何与任何“​​Value”字符串匹配的字符串   首先测试它是否导致有效的值参数对,和   只有在那之后才应该测试初始的varargin {:}元素   反对可选参数验证。

     

基本上,我说你不能称之为“可选”的论据   必须存在才能使解析器正常运行。

我发现的最后一个是引用他们的支持者,

  

感谢您在调查此问题时的耐心等待。在   您发送的示例中,'color'确实作为可选项使用   参数'形状'。这种情况正在发生,因为目前,位置   参数优先于名称/值对。我为此道歉   给您带来的不便。我已经分享了你的工作流程   与开发人员的关注和您的建议以及增强功能   请求已提交。它将在未来的版本中考虑   MATLAB。

答案 2 :(得分:0)

这实际上并不是一个错误。验证功能不够具体,这是一个问题。仅使用ischar作为验证函数意味着参数名称可能被误解为有效值。很可能,我希望您的输入具有一组固定的有效值,而您应该检查输入是否是该集合的有效成员。这是一个例子:

p = inputParser;
addOptional(p, 'shape', 'forgot', @(s) ismember(s, {'square', 'circle', 'triangle'}));
addParameter(p, 'color', 'k', @(c) ismember(c, 'ymcrgbwk'));

您可以根据需要使验证功能更复杂,可能会anonymous functions改为function handles而不是local functions。例如,您可以检查数据类型然后检查值,或者您可以检查'color'参数是a single character or an RGB triplet

可能导致混淆的部分原因是将'KeepUnmatched'设置为true,这将存储不匹配的参数值对,并且不会抛出与inputParser object的预期参数不匹配的任何错误。第二次编辑的第一个示例(使用numeric作为验证函数)在输入参数列表中找不到数值,因此将'shape'设置为默认值。由于解析器接下来会查找参数值对,因此字符串'nono''color'将成为不匹配的对,并存储在解析器对象的'Unmatched'属性中。仍在寻找有效的参数 - 值对,解析器只找到'vu',假设它是一个不匹配的参数字符串。

我遵循的一般经验法则:尽可能使您的验证功能具体化。