Summary
When using function argument validation that depends on multiple
arguments in a (Repeating)
arguments block, the current argument is passed
to the validation function normally while other arguments are passed as
partially-populated
cell arrays. This contasts with how things work in non-(Repeating)
arguments blocks. Is this the expected behavior or a bug?
Scenario
Consider the function dummy1
below, which uses the custom argument validation
function
mustBeEqualSize
to ensure that the arguments x
and y
have the same size.
Since the validation of y
depends on the value of x
, I'm calling this
"cross-argument" validation*.
*If there's a better term for this, please comment or edit.
function dummy1(x, y)
arguments
x (1,:)
y (1,:) {mustBeEqualSize(x,y)}
end
% Do something with x and y.
end
function mustBeEqualSize(a, b)
% Validates that function arguments have the same size.
if ~isequal(size(a), size(b))
eid = 'Size:notEqual';
msg = "Arguments must have the same size.";
throwAsCaller(MException(eid, msg))
end
end
As written, this form of argument validation works as expected:
dummy1(1:3, 4:6) % arguments have same size; validation passes (okay)
dummy1(1:3, 4:7) % arguments have different size; validation fails (okay)
In both cases, when mustBeEqualSize
is called during argument
validation for y
, both a
and b
are received as 1xN double arrays,
which matches my expectations:
% Inside call to mustBeEqualSize(x,y), when x=1:3, y=4:6 in dummy1
a =
1 2 3
b =
4 5 6
The problem arises when dummy1
is modified to accept repeating
arguments by adding (Repeating)
to the arguments block:
function dummy2(x, y)
arguments (Repeating)
x (1,:)
y (1,:) {mustBeEqualSize(x,y)}
end
% Do something with each pair of x-y arguments.
% In this body, both x and y will be 1xN cell arrays, where N is the
% number of argument groups passed.
end
Now when we call dummy2(1:3, 4:6)
, argument validation fails. Using the
debugger, I found that when mustBeEqualSize
is called during the
validation of y
, a
is received as a 1x1 cell array while b
remains a 1x3 double array:
% Inside call to mustBeEqualSize(x,y), when x=1:3, y=4:6 in dummy2
a =
1×1 cell array
{[1 2 3]}
b =
4 5 6
The issue is even more obvious when more repeating argument are used:
dummy2(1:3, 4:6, 1:3, 4:6, 1:3, 4:6) % 3 argument groups
results in
a =
1×3 cell array
{[1 2 3]} {0×0 double} {0×0 double}
b =
4 5 6
It seems that during the validation of y
in dummy2
, y
takes on the value of the
current argument being validated while x
is a (parially populated)
cell array buffer that MATLAB allocated to hold all of the x
-arguments
that were passed.
This of course breaks the cross-argument validation, since only the argument currently being validated actually presents itself as a single argument, while other arguments present themsevles as cell array buffers.
Question
Is the mismatch between how cross-argument validation works for (Repeating)
versus non-(Repeating)
arguments a bug, or is cross-argument validation with (Repeating)
arguments not supported in MATLAB? If this difference in behavior is expected, is there any way to make cross-argument validation work with (Repeating)
arguments?
The MATLAB docs say the following about argument validation with Repeating arguments
In the function, each repeating argument becomes a cell array with the number of elements equal to the number of repeats passed in the function call. The validation is applied to each element of the cell array.
which doesn't seem to shed any light on how cross-argument validation should work with repeating arguments.
Tested using MATLAB R2021a (9.10.0.1602886).