Why doesn't assignin work in this context?
Afficher commentaires plus anciens
I have a matlab function which creates a variable named 'duration'.
function doStuff()
duration = 5;
Inside the function I create a uicontrol edit box to allow changing the duration value.
uicontrol(panel, 'Style', 'edit', 'Callback', {@setEditBoxNumber, 'duration', 0, 15});
The callback is a local function.
function setEditBoxNumber(obj, ~, ivar, min, max)
value = str2double(get(obj, 'String'));
if isnan(value)
if ~isempty(ivar)
value = evalin('base', ivar);
end
else
value = clip(value, min, max);
end
set(obj, 'String', num2str(value));
if ~isempty(ivar)
assignin('base', ivar, value);
end
value = evalin('base', 'duration');
value = duration;
end
The last two lines are used for debugging purposes. If duration is set to 4 and I type '2' into the text box the string is properly converted to the number 2. The value returned by the bottom evalin call is 2, but the value of duration is still 4.
This is very confusing. If I type letters in the text box the str2double call returns NaN and the upper evalin call properly retrieves the value for duration. I tried using the caller workspace but there was no change in behavior.
1 commentaire
Tom
le 13 Août 2015
Réponses (1)
Walter Roberson
le 12 Août 2015
When you use
value = evalin('base', 'duration');
value = duration;
the first line does not change duration in the current workspace, only in the base workspace. The line after that uses the duration of the current workspace, where it has not been changed. Remove the semicolon from the end of the
value = evalin('base', 'duration');
line to see the value as fetched from the base workspace.
5 commentaires
Walter Roberson
le 13 Août 2015
You have done the assignin('base') and that affects the variable named by ivar in the base workspace. To check it you can pull the value back,
value = evalin('base', ivar)
Walter Roberson
le 13 Août 2015
What is the relationship between doStuff and setEditBoxNumber ? If doStuff is not calling setEditBoxNumber directly and setEditBoxNumber is not a nested function of doStuff then setEditBoxNumber cannot force doStuff's variables to change.
Consider having a handles.ivars structure and having setEditBoxNumber change the value in handles.ivars.(ivar) and then guidata(hObject, handles) to push the value upward. Then at at any point that doStuff suspects that the value might be changed and wants to fetch the new value, doStuff should
handles = guidata(TheFigureNumber);
and pull the values out of handles.ivars.duration
Tom
le 16 Août 2015
Walter Roberson
le 16 Août 2015
Modifié(e) : Walter Roberson
le 16 Août 2015
Callbacks are evaluated as if called from the base workspace. If the callback is defined as a nested routine then it can read and write variables in the nesting routine that are assigned values before the nested routine is defined.
function outer
a = 123;
function inner(src, event)
a = 456; %this changes outer's "a"
b = 789; %this changes a local variable "b"
end
b = -11111; %although this belongs to outer, it was not defined before inner() is defined so inner() does not have access to it
set(gcf, 'WindowButtonFcn', @inner)
end
Then the callback of inner() will change outer()'s value of "a", but outer() has already returned so outer() does not get to see the change. If you were to re-execute outer() then because it has the assignment to "a" it would change "a" back to 123. For this reason, functions that nest other functions often end up being "shells" that exist mostly to set something up, with all the real work being done by nested routines whose function handles get stored somewhere.
Catégories
En savoir plus sur Data Type Conversion dans Centre d'aide et File Exchange
Produits
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!