Isn't it dangerous to allow Comma-Separated-List functionality in indexed assignments?

조회 수: 2 (최근 30일)
I have a function below called renamefields() which, as the name suggests, renames a desired subset of struct array fields as desired. It works now, as the following simple example shows,
[S(1:2).a]=deal(10,20);
T=renamefields(S,'a','b');
[S.a]
ans = 1×2
10 20
[T.b]
ans = 1×2
10 20
Prior to getting it working, though, I had a bug in the code that I've also included below as renamefieldsBUG(). Repeating the steps above, you can see the effect:
T=renamefieldsBUG(S,'a','b');
[T.b]
ans = 1×2
10 10
I know why this occurs. It is because in the buggy version, the right hand side of the assignment S.(srcfields{j}) is a comma-separated list. When the left hand side of a comma-separated list assignment has only a single variable, all but the first element of the list is discarded (see doc). Is this not dangerous behavior, however? It seems like if you wanted this behavior, it should be done with an explicit command. Otherwise, as the example shows, code can be bug-prone.
function S=renamefields(S,srcfields,destfields)
%Rename fields
%
%S=renamefield(S,srcfields,destfields)
N=numel(S);
if ischar(srcfields), srcfields={srcfields}; end
if ischar(destfields), destfields={destfields}; end
M=numel(srcfields);
assert(M==numel(destfields),'src and dest length don''t agree.')
for i=1:N
for j=1:M
S(i).(destfields{j})=S(i).(srcfields{j});
end
end
S=rmfield(S,srcfields);
end
function S=renamefieldsBUG(S,srcfields,destfields)
%Rename fields
%
%S=renamefield(S,srcfields,destfields)
N=numel(S);
if ischar(srcfields), srcfields={srcfields}; end
if ischar(destfields), destfields={destfields}; end
M=numel(srcfields);
assert(M==numel(destfields),'src and dest length don''t agree.')
for i=1:N
for j=1:M
S(i).(destfields{j})=S.(srcfields{j}); %<----BUG: should be S(i) on right side
end
end
S=rmfield(S,srcfields);
end
  댓글 수: 2
Paul
Paul 2023년 2월 2일
Isn't this behavior needed when calling a function with fewer output arguments than the function actually returns? That is, I thought a function returns a CSL, the elements of which are paired up with the outputs on the calling side.
a = test
a = 1
Hmm, now that I've typed that, I'm not so sure that a CSL is the actual mechanism for return arguments.
function [a,b] = test
a = 1;
b = 2;
end
Matt J
Matt J 2023년 2월 2일
@Paul Isn't this behavior needed when calling a function with fewer output arguments than the function actually returns?
I have no issue with having that behavior in function call syntax. My issue is having it with indexing syntax.

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

답변 (1개)

Walter Roberson
Walter Roberson 2023년 2월 2일
Consider
x = rand(1,10);
y = power(max(x),2) %also known as y = max(x).^2
How many outputs does max(x) potentially have? Two. Should we require an explicit syntax for discarding all outputs other than the first? It could not be
y = power(discard_trailing_output(max(x)), 2)
-- not without a very serious backwards incompatibility.
Effectively, every function that potentially has more than one output, returns a comma separated list. A function that really cares can detect the situation by examining nargout and chosing not to assign to variables named in the corresponding output positions, or by choosing to assign only to as much of varargout as nargout says is used. But a relatively small fraction of functions do that; most return multiple variables effectively as CSL and MATLAB discards the extras.
  댓글 수: 2
Matt J
Matt J 2023년 2월 2일
편집: Matt J 2023년 2월 2일
Should we require an explicit syntax for discarding all outputs other than the first?
Yes, as I've suggested in my post, it would be sufficient to require a function call syntax. max() already has that syntax, so one is already alert to the fact that additional outputs are discarded.
What is treacherous in my posted example is that the behavior happens for indexing expressions. Normally, with indexing expressions, we are warned that the right side and left side don't match, e.g.,
x(1)=1:4
Unable to perform assignment because the indices on the left side are not compatible with the size of the right side.
Matt J
Matt J 2023년 2월 2일
편집: Matt J 2023년 2월 2일
What is also a bit strange to me is that the deal() command has the opposite behavior,
[a,b]=deal(1,2,3)
Error using deal
The number of outputs should match the number of inputs.
Why isn't the 3, which wasn't requested, simply discarded? To my tastes, it would be better/safer if deal would discard unrequested outputs. We could then use that to get this behavior if we wanted it.

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

카테고리

Help CenterFile Exchange에서 Logical에 대해 자세히 알아보기

제품


릴리스

R2022a

Community Treasure Hunt

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

Start Hunting!

Translated by