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?

 Respuesta aceptada

Stephen23
Stephen23 el 7 de Abr. de 2021
Editada: Stephen23 el 21 de Jun. de 2022
"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 comentarios

Bruno Luong
Bruno Luong el 7 de Abr. de 2021
Editada: Bruno Luong el 7 de Abr. de 2021
"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.
Stephen23
Stephen23 el 7 de Abr. de 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).

Iniciar sesión para comentar.

Más respuestas (1)

Bruno Luong
Bruno Luong el 7 de Abr. de 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
>>

5 comentarios

Yes, but deal isn't better than a cell array, right? (You actually used deal in addition to the cell array method)
Bruno Luong
Bruno Luong el 7 de Abr. de 2021
Editada: Bruno Luong el 7 de Abr. de 2021
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);

Iniciar sesión para comentar.

Categorías

Productos

Versión

R2020b

Etiquetas

Preguntada:

el 7 de Abr. de 2021

Editada:

el 21 de Jun. de 2022

Community Treasure Hunt

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

Start Hunting!

Translated by