Assignment of variables by comma separated lists

84 vues (au cours des 30 derniers jours)
broken_arrow
broken_arrow le 7 Avr 2021
Modifié(e) : Stephen23 le 21 Juin 2022
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?

Réponse acceptée

Stephen23
Stephen23 le 7 Avr 2021
Modifié(e) : Stephen23 le 21 Juin 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 commentaires
broken_arrow
broken_arrow le 7 Avr 2021
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 le 7 Avr 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).

Connectez-vous pour commenter.

Plus de réponses (1)

Bruno Luong
Bruno Luong le 7 Avr 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 commentaires
Tony Castillo
Tony Castillo le 27 Juil 2021
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
Stephen23
Stephen23 le 27 Juil 2021
[b2.BarWidth] = deal(0.4);

Connectez-vous pour commenter.

Tags

Produits


Version

R2020b

Community Treasure Hunt

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

Start Hunting!

Translated by