Argument validation for cell arrays?

조회 수: 36 (최근 30일)
Klaus
Klaus 2023년 9월 8일
편집: Klaus 2023년 9월 13일
I am looking for a way to express in a function validation block
arguments
% ...
end
Illegal use of reserved keyword "end".
that the argument must be a cell array of three-vectors.
The closest I came was to check that the argument is a cell array with a variable number of elements, as in this example script:
% should be accepted
example({ [0;0;0], [0;1;0], [1;1;0], [1;0;0] });
% should fail, because of the char-array
example({ [0;0;0], [0;1;0], [1;1;0], 'not allowed' });
% should fail, because of unexpected size of last vector
example({ [0;0;0], [0;1;0], [1;1;0], [1;0] });
% definition
function example(points)
arguments
points (1,:) cell
end
size(points)
end
Best regards,
Klaus
To summarize the answers
  • There is no builtin easy way to make such checks.
  • If needed, a custom mustBeASomething function has to be defined. Preferably with useful error messages.
  • Using user-defined classes would help further.
  댓글 수: 2
Mario Malic
Mario Malic 2023년 9월 8일
Hey, I am not sure if it is possible to validate your arguments within the argument block as I never used it, but here's an idea if you want to do by adding the code.
points1 = { [0;0;0], [0;1;0], [1;1;0], 'not allowed' };
test1 = string(cellfun(@class, points1, 'UniformOutput', false))
test1 = 1×4 string array
"double" "double" "double" "char"
if (numel(unique(test1)) > 1)
error("multiple variable types")
end
Warning: multiple variable types
points2 = { [0;0;0], [0;1;0], [1;1;0], [1;0] };
test2 = cellfun(@size, points2, 'UniformOutput', false)
test2 = 1×4 cell array
{[3 1]} {[3 1]} {[3 1]} {[2 1]}
test2Arr = cell2mat(test2');
if size(unique(test2Arr, 'rows'), 1) > 1
error ("different dimensions of points")
end
different dimensions of points
Klaus
Klaus 2023년 9월 8일
@Mario Malic While it would work, I was looking for something to leverage the advantages of the arguments syntax, which guarantees, that all arguments are covered, and all information is declaratively in one place.
The result would be something like
arguments
points(1,:) cell {mustBeListOf3Vectors(points)}
end
but if there are builtin capabilities, it would provide better readability.
If I'd design the code from scratch, I'd probably use
points(3,:) double
instead, and for the more complex structs-of-structs classdef with type-constrained properties.

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

채택된 답변

Stephen23
Stephen23 2023년 9월 8일
편집: Stephen23 2023년 9월 8일
"that the argument must be a cell array of three-vectors."
You can easily write your own argument validation function:
example({ [0;0;0], [0;1;0], [1;1;0], [1;0;0] });
ans = 1×2
1 4
%example({ [0;0;0], [0;1;0], [1;1;0], 'not allowed' });
example({ [0;0;0], [0;1;0], [1;1;0], [1;0] });
Error using solution>example
Invalid argument at position 1. Input must be a cell array of 3-element vectors
function example(points)
arguments
points cell {isCell3Vec}
end
size(points)
end
function isCell3Vec(C)
X = cellfun(@isnumeric,C)&cellfun(@numel,C)==3;
assert(all(X(:)),'Input must be a cell array of 3-element vectors')
end
  댓글 수: 2
Steven Lord
Steven Lord 2023년 9월 8일
While cellfun is compact, it's also sometimes cryptic. I'd also suggest a slightly more descriptive / targeted error message, and in support of that I'd use a simple loop in the validator.
For the case where one of the inputs is a numeric array with 3 elements but is not a vector (remember, by the definition codified in the isvector function a vector must be a 2-D array.)
try
example({1:3, 4:6, reshape(7:9, [1 1 3])})
catch ME
fprintf("Call threw error:\n%s", ME.message)
end
Call threw error: Invalid argument at position 1. Element 3 of the input is not a vector.
Wrong length numeric vector:
try
example({1:3, 4:7})
catch ME
fprintf("Call threw error:\n%s", ME.message)
end
Call threw error: Invalid argument at position 1. Element 2 of the input is not 3 elements long.
Not numeric but a 3 element vector:
try
example({'abc', 1:3, 4:6})
catch ME
fprintf("Call threw error:\n%s", ME.message)
end
Call threw error: Invalid argument at position 1. Element 1 of the input is not numeric.
function example(points)
arguments
points cell {isCell3Vec}
end
size(points)
end
function isCell3Vec(C)
for n = 1:numel(C)
x = C{n};
assert(isnumeric(x), "Element " + n + " of the input is not numeric.")
assert(numel(x) == 3, "Element " + n + " of the input is not 3 elements long.")
assert(isvector(x), "Element " + n + " of the input is not a vector.")
end
end
Mario Malic
Mario Malic 2023년 9월 10일
Thanks Steven, very informative.

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

추가 답변 (0개)

카테고리

Help CenterFile Exchange에서 Characters and Strings에 대해 자세히 알아보기

제품


릴리스

R2023a

Community Treasure Hunt

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

Start Hunting!

Translated by