Is there a good way to validate that all inputs to a function have compatible sizes when using a (Repeating) arguments block?
21 次查看(过去 30 天)
显示 更早的评论
Setup
Let's say I have some function that a number of arrays as an input and does something with them that requires the arrays to have compatible sizes (i.e., to have the same sizes after implicit singleton dimension expansion). I have written a function "mustBeCompatibleSize" that throws an error if it's arguments have incompatible sizes. This works as expected. It correctly points out which argument is causing the error to the user.
function multiArrayOperation1(Array1, Array2, Array3)
arguments
Array1;
Array2 {mustBeCompatibleSize(Array1, Array2)};
Array3 {mustBeCompatibleSize(Array1, Array2, Array3)};
end
% Do something with Array1, Array2, and Array3.
end
For example, calling the following will result in MATLAB telling the user that the 3rd argument was not compatible with previous arguments.
multiArrayOperation1(ones(5, 1), ones(1, 5), ones(5, 6))
I'm adding the validation function for completeness.
function [] = mustHaveCompatibleSizes(Arrays)
arguments (Repeating)
Arrays;
end
maxInputDim = max(cellfun(@(x) ndims(x), Arrays));
inputDims = cell2mat(cellfun(@(x) size(x, 1:maxInputDim).', Arrays, UniformOutput=false)).';
outputDims = max(inputDims, [], 1);
isMismatch = any((inputDims ~= outputDims) & (inputDims ~= 1), 1);
if any(isMismatch)
throwAsCaller(MException("MATLAB:mustHaveCompatibleSizes", ...
"Invalid argument at position %d. Arguments must have compatible sizes", ...
find(isMismatch, 1)));
end
end
Issue
The issue comes about when I want to make a function that accepts any number of input arrays, using the (Repeating) arguments block, like in the example below. This example does not work, as the argument validator passes only one element at a time into the "mustBeCompatibleSize" function, and thus no error is thrown.
function multiArrayOperation2(Arrays)
arguments (Repeating)
Arrays {mustBeCompatibleSize};
end
% Do something with Arrays.
end
Calling the following does not result in an error being thrown.
multiArrayOperation2(ones(5, 1), ones(1, 5), ones(5, 6))
Nonoptimal Solution
Of course, we can just call the validation function manually after the arguments block. However, this does not display to the user which argument is causing the error as it does in the first example, and doesn't really utilize the arguments block for validation.
function multiArrayOperation3(Arrays)
arguments (Repeating)
Arrays;
end
mustBeCompatibleSize(Arrays{:});
% Do something with Arrays.
end
While the following code throws an error as it should, the user is not informed which specific argument is causing the error.
multiArrayOperation3(ones(5, 1), ones(1, 5), ones(5, 6))
Question
Is there a better solution to this issue? Hopefully, there is a way to implement something similar to the second example.
1 个评论
chrisw23
2022-11-8
The Repeating attribute will only work if you really have repeating arguments like
multiArrayOperation2(Arrays,Arrays,Arrays)
arguments (Repeating)
采纳的回答
Andrew Ouellette
2022-11-10
Hi Matthew,
I was able to achieve the behavior you desire by looping through the variable arguments and passing the argument number to the check function.
function multiArrayOp(varargin)
for ii = 2:nargin
mustBeCompatibleSize(ii,varargin{1:ii})
end
end
I added an additional input before the repeating arrays so that you can tell which input is being evaluated.
function [] = mustBeCompatibleSize(nArray,Arrays)
arguments
nArray
end
arguments (Repeating)
Arrays;
end
maxInputDim = max(cellfun(@(x) ndims(x), Arrays));
inputDims = cell2mat(cellfun(@(x) size(x, 1:maxInputDim).', Arrays, UniformOutput=false)).';
outputDims = max(inputDims, [], 1);
isMismatch = any((inputDims ~= outputDims) & (inputDims ~= 1), 1);
if any(isMismatch)
msg = sprintf('Invalid argument at position %g. Arguments must have compatible sizes.',nArray);
throwAsCaller(MException("MATLAB:mustHaveCompatibleSizes", msg));
end
end
更多回答(0 个)
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Loops and Conditional Statements 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!