Isn't it dangerous to allow Comma-Separated-List functionality in indexed assignments?
2 views (last 30 days)
Show older comments
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]
[T.b]
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]
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
Answers (1)
Walter Roberson
on 2 Feb 2023
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 Comments
See Also
Categories
Find more on Entering Commands in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!