I am using findArea as an example in documentation to parse and validate required,optional and pair-value arguments of a function. I have copied findArea function here to demonstrate the possible bug in matlab parse function.
function a = findArea(width,varargin)
defaultHeight = 1;
defaultUnits = 'inches';
defaultShape = 'rectangle';
expectedShapes = {'square','rectangle','parallelogram'};
p = inputParser;
validScalarPosNum = @(x) isnumeric(x) && isscalar(x) && (x > 0);
addRequired(p,'width',validScalarPosNum);
addOptional(p,'height',defaultHeight,validScalarPosNum);
addParameter(p,'units',defaultUnits,@isstring);
addParameter(p,'shape',defaultShape,...
@(x) any(validatestring(x,expectedShapes)));
parse(p,width,varargin{:});
a = p.Results.width*p.Results.height;
end
Now I am calling the findArea function as given in documentation:
1) a = findArea(7,3,'shape','square');
As expected Validation of 7 (first input) and 3 (second input) is done with validScalarPosNum. For Name-Value pair, validation of value of "shape" is done with validatestring. This is fine.
2) a = findArea(7,'shape','square');
Now the problem is here. Validation of 7 (first input) is done with validScalarPosNum. However, the validation of second input "shape" is also done with validScalarPosNum. This is possibly bug. Then as in 1) Validation of value of "shape" is done with validatestring. The problem arises when the optional input is defined in the function (in this example "height"), but not passed in the function arguments.
Does anybody has an idea what is going on here?
Thank you very much.

 채택된 답변

Ameer Hamza
Ameer Hamza 2020년 4월 2일
편집: Ameer Hamza 2020년 4월 3일

0 개 추천

This does seem to be a limitation in the implementation of inputParser. Following code show a case where the parser will fail. In this code, the second optional input is a char array.
function a = findArea(width, varargin)
defaultHeight = 1;
defaultUnits = 'inches';
defaultShape = 'rectangle';
expectedShapes = {'square','rectangle','parallelogram'};
p = inputParser;
validScalarPosNum = @(x) isnumeric(x) && isscalar(x) && (x > 0);
validScalarPosNum2 = @(x) ischar(x); % <---- the optional parameter is char array
addRequired(p,'width',validScalarPosNum);
addOptional(p,'height',defaultHeight,validScalarPosNum2);
addParameter(p,'units',defaultUnits,@isstring);
addParameter(p,'shape',defaultShape,...
@(x) any(validatestring(x,expectedShapes)));
parse(p,width,varargin{:});
a = p.Results;
end
now call it like this
>> findArea(7, 'shape', 'square')
Error using findArea (line 14)
No value was given for 'square'. Name-value pair arguments require a name
followed by a value.
I skipped the optional parameter height, but the parser failed to note that.
I guess this is done intentionally by MATLAB to avoid some kind of ambiguity in parsing the inputs. For example, in this case, it is easy to tell since we are using a single optional input. But consider a function that takes several optional inputs and parameters. In that case, it will become difficult for the parser to guess which values are optional inputs and which are parameters.
Note that the parser will only fail if you are taking character array as inputs for optional parameters. I guess the MATLAB expects that the character arrays should be input using parameters.

댓글 수: 3

Thank you for the Answer. Regarding your example of optional parameter height, now I know where the problem is. As mentioned in the documentation, we need to specify validation function with possible values for the optional input string or char as below
expectedHeight = {'1','2','3'};
validScalarPosNum2 = @(x) any(validatestring(x,expectedHeight));
Now calling like this
findArea(7, 'shape', 'square')
This will not throw error as it validates second input 'shape' with validScalarPosNum2 and since it is neither or '1','2','3', it assumes that second input is name value pair.
But the real problem is it is not always possible to validate optional input string or char, e.g. the optional input can take infinite possible values.
Because of its limitations, I will switch to use new input check functionality "arguments" which was introduced in R2019b.
Ameer Hamza
Ameer Hamza 2020년 4월 3일
Good observation. I agree that the optional input should be able to take arbitrary character array as input. I hope that "arguments" is able to handle such cases.
FWIW, It is possible to get arbitrary length char arrays as optional input. The only limitation now is that it should not be the same as any other parameter.
function a = findArea(width, varargin)
defaultHeight = 1;
defaultUnits = 'inches';
defaultShape = 'rectangle';
expectedShapes = {'square','rectangle','parallelogram'};
p = inputParser;
validScalarPosNum = @(x) isnumeric(x) && isscalar(x) && (x > 0);
validScalarPosNum2 = @(x,p) ischar(x) && ~ismember(x, p.Parameters); % <---- the optional parameter is char array
addRequired(p,'width',validScalarPosNum);
addOptional(p,'height',defaultHeight,@(x) validScalarPosNum2(x,p));
addParameter(p,'units',defaultUnits,@isstring);
addParameter(p,'shape',defaultShape,...
@(x) any(validatestring(x,expectedShapes)));
parse(p,width,varargin{:});
a = p.Results;
end

댓글을 달려면 로그인하십시오.

추가 답변 (0개)

카테고리

도움말 센터File Exchange에서 Data Type Identification에 대해 자세히 알아보기

제품

릴리스

R2019b

질문:

2020년 4월 2일

댓글:

2020년 4월 3일

Community Treasure Hunt

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

Start Hunting!

Translated by