MATLAB Answers

Assignment of variables by comma separated lists

14 views (last 30 days)
I have some trouble understanding the behaviour of comma separated lists. Consider
A = struct('number', cell(1, 5));
If I want to assign numbers from 1 to 5, I have to introduce an auxiliary cell array:
numbers=num2cell(1:5);
[A.number]=numbers{:};
The direct way
[A.number]=1,2,3,4,5;
doesn't work although numbers{:} and 1,2,3,4,5 return the exact same result when entered at the command line. Why is that? And is there a more efficient way to assign a vector or an array of values to a struct than using an auxiliary cell array?

Accepted Answer

Stephen Cobeldick
Stephen Cobeldick on 7 Apr 2021
Edited: Stephen Cobeldick on 7 Apr 2021
"Why is that?"
The answer is surprisingly simple: the explicit syntax
X,Y,Z
is considered as three separate evaluations, much as if you had written them on three different lines:
X
Y
Z
This is explained in the documentation for the comma, and also in the documentation for entering statements, which states "You also can enter more than one statement on the same line by separating statements. To distinguish between commands, end each one with a comma or semicolon. Commands that end with a comma display their results, while commands that end with a semicolon do not." This means you will get exactly the same error, even if you just try to allocate one array on the RHS to multiple arrays/locations on the LHS:
Of course we cannot allocate one array to three arrays! But we can make it work (and also demonstrate exactly what is happening) by simply replacing the first argument with a function that returns sufficient outputs:
>> A = struct('number', cell(1,3));
>> [A.number] = X,2,3
A =
1x3 struct array with fields:
number
ans =
2
ans =
3
>> A.number
ans =
1
ans =
Inf
ans =
NaN
Note that the 2 and 3 are parsed, displayed, and discarded! The function I used is given here:
function [x,y,z] = X()
x = 1;
y = Inf;
z = NaN;
end
In contrast, the comma-separated lists that are generated from either a cell array or a structure are all forms of indexing, which means that ultimately they call subsref, which apparently can return multiple outputs (as in general MATLAB functions can). As subsref is builtin we cannot easily add breakpoints :(
My guess is that this is limited to RHS explicitly-written comma-separated lists only, but this is just a guess.
Summary:
  • explicitly-written comma-separated lists on the RHS request all of the outputs from the first list argument.
  • generated comma-separated lists (attempt to) return as many outputs from subsref as the LHS requests.
  3 Comments
Stephen Cobeldick
Stephen Cobeldick on 7 Apr 2021
"I think this is just a question of design decision."
Agreed. There is a conflict between the syntax of using commas to separate expressions to evaluate vs comma-separated list, and to resolve that conflict is likely to be a design decision.
"so the output of subsref is returned like a comma separated list only if nargout==0"
If nargout==0 then subsref would return nothing, which is not generally why people use comma-separated lists.
LIke any function, the number of outputs provides is demand driven (up to the number that are specified internally).

Sign in to comment.

More Answers (1)

Bruno Luong
Bruno Luong on 7 Apr 2021
Use deal
>> A = struct('number', cell(1, 5));
>> A
A =
1×5 struct array with fields:
number
>> n=1:5;
>> c=num2cell(n);
>> [A.number]=deal(c{:})
A =
1×5 struct array with fields:
number
>> A.number
ans =
1
ans =
2
ans =
3
ans =
4
ans =
5
>>
  3 Comments

Sign in to comment.

Tags

Products


Release

R2020b

Community Treasure Hunt

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

Start Hunting!