Reputation: 13
I have some troubles with a Matlab recursive function that I created in order to browse a data structure and modify each field that contains a path starting by a keyword.
My function that replaces a relative path starting by a keyword by an absolute path works perfectly fine and has already been tested (for instance, '$KEYWORD\Desktop\Documents' will be replaced by 'C:\Users\Name\Desktop\Documents')
I am trying to apply this function to a data structure that contains many (too many) fields, with a recursive function. I want this recursive function to browse my data structure, and as soon as it detects a char parameter starting by $KEYWORD, it changes the value by an absolute path stored in an environment parameter. Here is my code:
function newStruct = browse_struct(initStruct)
fields = fieldnames(initStruct);
n_fields = length(fields);
for n = 1 : n_fields
val = getfield(initStruct, fields{n});
if isstruct(val)
browse_struct(val);
elseif( ischar(val) && val(1)=='$' )
newVal = replace_keyword(val);
newStruct = setfield(initStruct, fields{n}, newVal);
end
end
end
When I run my code in debug mode, I see that my function browses entirely my data structure, and that the fields of interest are being replaced by what I want, but when the run is over, the new structure is identical to initial one. No field has been changed, so in the end I still have relative paths starting by $KEYWORD, while it should be an absolute path instead.
I also tried to replace the line 7 (the one just under the if condition) by:
newStruct = browse_struct(val)
And it doesn't work either, it completely destroys the initial structure.
I don't know how to fix that problem. Can someone help me please? Thanks a lot.
Upvotes: 1
Views: 950
Reputation: 4552
Problem 1: In your function you are applying changes to newStruct
but keep using initStruct
for new changes, so you are overriding previous changes to newStruct
.
Solution: when you pass a struct (or any object) to a function in MATLAB, you pass it by value, so the original struct does not change. You can simply remove newStruct
from the function and only work with initStruct
.
Problem 2: browse_struct(val);
does not change the struct, and newStruct = browse_struct(val);
changes the struct to its field.
Solution: Use newStruct = setfield(initStruct, fields{n}, browse_struct(val));
The corrected function:
function initStruct = browse_struct(initStruct)
fields = fieldnames(initStruct);
n_fields = length(fields);
for n = 1 : n_fields
val = getfield(initStruct, fields{n});
if isstruct(val)
initStruct = setfield(initStruct, fields{n}, browse_struct(val));
elseif( ischar(val) && val(1)=='$' )
newVal = replace_keyword(val);
initStruct = setfield(initStruct, fields{n}, newVal);
end
end
end
Instead of using getfield
and setfield
, MATLAB suggests "Use dynamic field names with structures" so you can modify the function like this:
function initStruct = browse_struct(initStruct)
fields = fieldnames(initStruct);
n_fields = length(fields);
for n = 1 : n_fields
val = initStruct.(fields{n});
if isstruct(val)
initStruct.(fields{n}) = browse_struct(val);
elseif( ischar(val) && val(1)=='$' )
newVal = replace_keyword(val);
initStruct.(fields{n}) = newVal;
end
end
end
Upvotes: 2