Copied struct ends up in "ans" instead of new struct (within function)
Afficher commentaires plus anciens
--- Question:---
Hi,
This code results in "Dependent" being copied to "ans", but no Dependent2 is generated. Im sure there's a simple explanation, but I cant find one. Within the command window, this code runs perfectly fine. Thanks for any help! :)
function [Dependent] = tilt_every_range_into_a_different_dimension(Dependent)
Dependent2 = Dependent;
end
--- Further Details: ---
This is the mentioned Struct. The cells are 1x1000 Matrices each (just a linspace(1,50,1000)).
>> whos Dependent
Name Size Bytes Class Attributes
Dependent 1x1 17432 struct
>> Dependent
Dependent =
struct with fields:
value: {1×3 cell}
name: {'Y' 'U' 'L'}
type: {["ranged"] ["ranged"] ["ranged"]}
The following is the initial code. The same problem occurs. Instead of overwriting Dependent.value, the result is stored in ans.
The eval function basically excutes:
↓ ↓ - number of ones varies depending on n
Dependent.value{n} = reshape(Dependent.value{n},[1,1,length(Dependent.value{n})])
function [Dependent] = tilt_every_range_into_a_different_dimension(Dependent)
code_insertion1 = "1,";
code_insertion2 = "length(Dependent.value{n})";
Dependent2.value{1} = Dependent.value{1}';
for n = 2:length(Dependent.name)
if (strcmp(string(Dependent.type{n}), "ranged")==1)
code_insertion2 = append(code_insertion1,code_insertion2) ;
code_insertion3 = append("Dependent.value{n} = reshape(Dependent.value{n},[", code_insertion2, "])");
fprintf(code_insertion3 + " n= " + string(n))
eval(code_insertion3);
end
end
end
1 commentaire
I note that your function always transposes value{1}, but only reshapes value{2:end} after matching the "ranged" text. This seems inconsistent: should the first one also be checked for the "ranged" match? Or is the first value an exception to the rule?
Now that I look more carefully, in fact you assign value{1} to a structure named Dependent2, but you never do anything with the structure so it will simply get discarded. There does not seem to be much point in that.
Réponses (2)
I think you will find that Dependent2 is generated.
After that, the end of the function is reached, and MATLAB removes all local variables, including Dependent2 .
Variables assigned to within a function only affect calling functions under narrow circumstances:
- the variables assigned to are marked as global in the function and in the calling function; or
- the variables assigned to are "shared" variables being assigned to inside a nested function
outer_function();
whos
function outer_function
shared_variable = 123;
function inner_function
shared_variable = 456;
unshared_variable = 789;
whos
end
whos
inner_function();
whos
end
Notice that unshared_variable did not make it into outer_function . The shared variable must be assigned to before the nested function is defined (not before it is executed.)
"The eval function basically excutes: number of ones varies depending on n ...
Dependent.value{n} = reshape(Dependent.value{n},[1,1,length(Dependent.value{n})])"
Ummm... you really should avoid evil EVAL for such simple processing as this. Your code is complex, inefficient, indirect, and completely obfuscates the code intent. Writing code in this way is going to make your life much harder in the long term: https://www.mathworks.com/matlabcentral/answers/304528-tutorial-why-variables-should-not-be-named-dynamically-eval
Your question (and the way that you seem to have called that function) implies that you think that the variable names used inside the function must be the same as the variable names used as inputs/outputs. In fact they are totally unrelated, which is rather the point of writing functions. Question: do we know what variable names are used inside SQRT() function? Answer: no, nor does it matter when we call it. A function is a black box, what happens inside should not matter to the rest of the world.
And the basic answer to your question is that you need to specify the output when you call the function:
Y = myfun(X)
How to call functions with output arguments is explained in the introductory tutorials (strongly recommended):
You can replace that very unfortunate, complex, inefficient code with ONES() and indexing:
A = struct('value',{{1:3,4:6,7:9}}, 'name',{{'Y','U','L'}}, 'type',["ranged","ranged","ranged"])
B = myfun(A)
And there you are: much simpler, much more efficient code without any ugly anti-pattern EVAL anywhere.
function S = myfun(S)
for k = 1:numel(S.name)
V = ones(1,max(2,k));
V(k) = numel(S.value{k});
S.value{k} = reshape(S.value{k},V);
end
end
Note that I did not check the "ranged" criteria, because your own code is inconsistent on this.
Also note that I also replaced the cell array of scalar strings, which the MATLAB documentation specificially advises to avoid, because it has none of the benefits of using string arrays and all of the disadvantages of using cell arrays. The documentation makes this clear: "When you have multiple strings, store them in a string array, not a cell array. Create a string array using square brackets, not curly braces. String arrays are more efficient than cell arrays for storing and manipulating text.... Avoid using cell arrays of strings. When you use cell arrays, you give up the performance advantages that come from using string arrays."
Perhaps this task might be easier if you had used a non-scalar structure for the whole thing...
but at the very least, stop relying on evil EVAL for such basic operations.
Catégories
En savoir plus sur Variables dans Centre d'aide et File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!