Assignment of variables by comma separated lists

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?

 채택된 답변

Stephen23
Stephen23 2021년 4월 7일
편집: Stephen23 2022년 6월 21일

0 개 추천

"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 syntactical:
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 as the LHS requests.

댓글 수: 3

Bruno Luong
Bruno Luong 2021년 4월 7일
편집: Bruno Luong 2021년 4월 7일
"The answer is surprisingly simple: the explicit syntax X,Y,Z is considered as three separate evaluations, just as if you had written them on three different lines."
It could still remain as factor of confusion for people who is new to comma list. Why comma list can only be created from cell / struct but not from a list of separate evaluations separated by comma? After call I use the work "list' and "comma" to describe such thing, which is not a "comma list" as TMW defines it.
I think this is just a question of design decision.
Ah, so the output of subsref is returned like a comma separated list only if nargout==0 and is stored to the provided output variables otherwise, while the comma separated input is always processed number by number and that causes the problem. Thanks a lot.
"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).

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

추가 답변 (1개)

Bruno Luong
Bruno Luong 2021년 4월 7일

0 개 추천

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
>>

댓글 수: 5

Yes, but deal isn't better than a cell array, right? (You actually used deal in addition to the cell array method)
In this case no, but yo could look at the doc of deal for cases where directly using cell does not work.
In older MATLAB, the syntax
[...] = c{:}
throws an error. The new syntax is just an convenient extension of deal.
Personaly I never use those shortcut syntax in my code, it is as dangerous as length(); squeeze, etc...
Ah, ok. Thank you.
Dear all,
I have a similar error message but in this case is because I just want to stack some values in a Bar plot, do you have any insights to overcome this?
Assigning to 2 elements using a simple assignment statement is not supported. Consider
using comma-separated list assignment.
Error in barconvariasVariables (line 20)
b2.BarWidth = 0.4;
energy_=linspace(1000, 3000, 12)';
cons_=linspace(900, 2300, 12)';
g_c= linspace(700, 2000, 12)';
HDW_c=linspace(100, 300, 12)';
Power_=linspace(1000, 3000, 12)';
Sp_ =linspace(10, 30, 12)';
EV_=linspace(500, 1900, 12)';
COF=3.7;
n=12;
U1=[energy_, (cons_ + g_c + HDW_c)*(COF-1)];
U2=[(Power_ + Sp_ + EV_), (cons_ + g_c + HDW_c)*COF];
b1= bar(U1,'stacked');
b1(1).BarWidth = 0.4;
hold on;
b2=bar(U2,'stacked');
b2.BarWidth = 0.4;
b2.XData = (1:n) - 0.5; % move bars left
xlabel('Months', 'FontWeight','bold')
ylabel('Consumption vs RES (kWp)', 'FontWeight','bold')
grid on
[b2.BarWidth] = deal(0.4);

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

카테고리

도움말 센터File Exchange에서 Deploy to C++ Applications Using mwArray API (C++03)에 대해 자세히 알아보기

제품

릴리스

R2020b

태그

질문:

2021년 4월 7일

편집:

2022년 6월 21일

Community Treasure Hunt

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

Start Hunting!

Translated by