Can Matlab's arguments function handle structs

Hi,
I was wondering if it is possible to do argument validation with Matlab's arguments function like in the following example
function foo(Struct)
arguments
Struct.A double = 1
Struct.B double = 2
Struct.C char = 'hello
end
...
end

답변 (2개)

Sriram Tadavarty
Sriram Tadavarty 2020년 4월 25일
편집: Sriram Tadavarty 2021년 5월 7일
Hi Clownfish,
The function validation with input structure is not possible directly, instead, you can pass the structure as name value pairs to the function. Look at the Name-Value pair section here.
The valid function calls to validate the function posted in the question are:
foo("A",100,"B",25,"C","Arguments")
foo('A',100,'B',25,'C','Arguments')
% From R2021a onwards, the following are also possible
foo(A = 100, B = 25, C = "Arguments")
foo(A = 100, C = 'Arguments')
For the script you have provided, you can do slight modifications to check if it works, as shown below:
function [a,b,c] = foo(Struct)
arguments
Struct.A double = 1
Struct.B double = 2
Struct.C char = 'hello'
end
a = Struct.A;
b = Struct.B;
c = Struct.C;
end
>> foo % outputs 1
>> [a,b,c] = foo % Outputs a with value 1, b with value 2 ,and c with value 'hello'
>> [a,b,c] = foo("A",100,"B",25,"C","Arguments") % Outputs a with 100, b with 25, and c with 'Arguments'
Hope this helps.
Regards,
Sriram
PS: Updated the answer to make it clear. See the comments for more details.

댓글 수: 7

Using an actual struct as input (like the poster asked) does not work though:
>> [a,b,c] = foo(struct("A",100,"B",25,"C","Arguments"))
Error using foo
Invalid argument list. Check for wrong number of positional arguments or placement of positional arguments after name-value pairs. Also, check for name-value pairs with invalid names or not specified in pairs.
does not work though. Is it possible to do this without defining custom validation, just like what is possible for the inputParser?
Matt J
Matt J 2020년 7월 10일
편집: Matt J 2020년 7월 10일
It's probably a recent upgrade. In R2020a, it does work:
K>> [a,b,c] = foo("A",100,"B",25,"C","Arguments")
a =
100
b =
25
c =
'Arguments'
You are still not passing in a struct as Robert mentions but Name, Value Pairs.
The answer does say,
"Provided you need to input the structure as name value pairs to the function rather than structure itself"
The suggestion in the answer was to use the fields of the structure as name value pairs to function rather than the structure itself. Since, structure is not accepted directly to perform validation. It can't be used directly as inputParser.
Instead of doing this
[a,b,c] = foo(struct("A",100,"B",25,"C","Arguments"))
The suggestion was to perform the below:
foo("A",100,"B",25,"C","Arguments")
Observe the possible ways of calling the function having structure input argument with the example shown here. Though you have structure input, you cannot pass it as structure directly, rather you can pass them as name,value arguments.
For example, you can add validation function to fields and check if that works or not:
function [a,b,c] = foo(Struct)
arguments
Struct.A double {mustBePositive} = 1
Struct.B double {mustBeNonnegative} = 2
Struct.C char = 'hello'
end
a = Struct.A;
b = Struct.B;
c = Struct.C;
end
Now try this,
>> [a,b,c] = foo("A",0,"B",-1,"C","Arguments"); % You get the below error
Error using foo
Invalid name-value argument 'A'. Value must be positive.
>> [a,b,c] = foo("A",1,"B",-1,"C","Arguments"); % You get the below error
Error using foo
Invalid name-value argument 'B'. Value must be nonnegative.
Hope this helps.
Regards,
Sriram
Thanks Sriram for the answer.
I am interested in this question because arguments is a great fearture, but it will kill back-compatibility for my already written functions, which are written to be called with struct options.
Is Mathworks working on the solution here?
Thanks @Sriram Tadavarty for the answer. As already mentioned before, this is an issue if you want to replace the old inputParser (which allowed struct expansion) with the new arguments validation. Please allow the following syntax
arguments(StructExpand=true)
...
end
which allows to call either
foo("A", 100)
or
s.A = 100
foo(s)
This would ensure compatibility with the old inputParser

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

Walter Roberson
Walter Roberson 2021년 5월 7일
It does not appear to be possible.
One work-around would be
temp = [string(fieldnames(Struct)), struct2cell(Struct)].';
foo(temp{:});
after which, as @Sriram Tadavarty shows, you can validate in the form of a structure. Their answer shows what is actually possible; I am only adding this because of complaints that there needs to be an explicit "No" for the question as asked

댓글 수: 4

A different workaround:
nvp = namedargs2cell(Struct); foo(nvp{:});
Similar to @Walter Roberson's suggestion, using a built-in MATLAB function to transform the structure to name-value pair arguments.
@Walter Roberson I think this solution runs into a problem is the values are not strings. In the code below the value should be 2, but it is instead "2" so when I have a validator value (1,1) {mustBeNumeric} it will throw an error because "2" is a string.
Perhaps using value (1,1) double will cast the string into a double, but that is kind of defeating the purpose of the input validator
y.name = "b"; y.value = 2;
nvp = [string(fieldnames(y)) struct2cell(y)].'
nvp = 2×2 string array
"name" "value" "b" "2"
nvp{:}
ans = 'name'
ans = 'b'
ans = 'value'
ans = '2'
@Jeremy Berke: STRING is not required, you can just use the cell array instead:
y.name = "b";
y.value = 2;
y.hello = sqrt(2);
y.world = {'cat','hat'};
c = [fieldnames(y),struct2cell(y)].'
c = 2x4 cell array
{'name'} {'value'} {'hello' } {'world' } {["b" ]} {[ 2]} {[1.4142]} {1x2 cell}
c{:}
ans = 'name'
ans = "b"
ans = 'value'
ans = 2
ans = 'hello'
ans = 1.4142
ans = 'world'
ans = 1x2 cell array
{'cat'} {'hat'}

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

카테고리

도움말 센터File Exchange에서 Argument Definitions에 대해 자세히 알아보기

제품

릴리스

R2019b

질문:

2020년 4월 25일

댓글:

2024년 3월 28일

Community Treasure Hunt

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

Start Hunting!

Translated by