Есть ли способ нажать рабочее пространство MATLAB на стек?
Кто-нибудь знает, возможно ли иметь стек рабочих областей в MATLAB? Было бы очень удобно, если не сказать больше.
Мне нужно это для исследования. У нас есть несколько сценариев, которые взаимодействуют интересными способами. Функции имеют локальные переменные, но не скрипты...
Ответы
Ответ 1
Регулярный стек вызовов функции Matlab сам по себе представляет собой стек рабочих областей. Просто использование функций - это самый простой способ его использования, и Matlab copy-on-write делает это достаточно эффективным. Но это, вероятно, не то, о чем вы просите.
Существует естественное соответствие между рабочими пространствами и структурами, поскольку одинаковые идентификаторы действительны для имен переменных и структурных полей. Они оба по сути являются идентификаторами = > Mxarray-сопоставлениями.
Вы можете использовать whos
и evalin
для захвата состояния рабочей области в структуру. Используйте вектор ячейки, чтобы реализовать их стек. (Структурный массив не будет работать, потому что он требует однородных имен полей.) Стек может быть сохранен в appdata, чтобы предотвратить его появление в самой рабочей области.
Вот функции push и pop для этой техники.
function push_workspace()
c = getappdata(0, 'WORKSPACE_STACK');
if isempty(c)
c = {};
end
% Grab workspace
w = evalin('caller', 'whos');
names = {w.name};
s = struct;
for i = 1:numel(w)
s.(names{i}) = evalin('caller', names{i});
end
% Push it on the stack
c{end+1} = s;
setappdata(0, 'WORKSPACE_STACK', c);
function pop_workspace()
% Pop last workspace off stack
c = getappdata(0, 'WORKSPACE_STACK');
if isempty(c)
warning('Nothing on workspace stack');
return;
end
s = c{end};
c(end) = [];
setappdata(0, 'WORKSPACE_STACK', c);
% Do this if you want a blank slate for your workspace
evalin('caller', 'clear');
% Stick vars back in caller workspace
names = fieldnames(s);
for i = 1:numel(names)
assignin('caller', names{i}, s.(names{i}));
end
Ответ 2
Похоже, вы хотели бы переключаться между рабочими пространствами переменных. Лучший способ, я могу думать, это использовать SAVE, CLEAR и LOAD команды для перемещения наборов переменных между MAT файлами и рабочей областью:
save workspace_1.mat %# Save all variables in the current workspace
%# to a .mat file
clear %# Clear all variables in the current workspace
load workspace_2.mat %# Load all variables from a .mat file into the
%# current workspace
Ответ 3
Замечательно. (Не нашли, используя 0 с getappdata, зарегистрированным где-нибудь... так что это может быть возможно в будущем.) Добавили push и pop в мою библиотеку util, а также следующее:
pop_workspace(keep_current)
% keep_current: bool: if true, current vars retained after pop
. . .
if (~keep_current)
evalin('caller','clear');
end
Небольшое творчество, и можно сохранить только избранные вары и избежать перезаписи поп-музыки. Я нашел, что мне также нужна следующая функция в моей работе:
function pull_workspace(names)
% pulls variablesin cell array names{} into workspace from stack without
% popping the workspace stack
%
% pulled variable will be a local copy of the stack variable,
% so modifying it will leave the stack variable untouched.
%
if (~exist('names','var') || isempty(names))
pull_all = true;
else
pull_all = false;
% if names is not a cell array, then user gave us
% just 1 var name as a string. make it a cell array.
if (~iscell(names))
names = {names};
end
end
% Peek at last workspace on stack
c = getappdata(0, 'WORKSPACE_STACK');
if isempty(c)
warning('Nothing on workspace stack');
return;
end
s = c{end};
% Stick vars back in caller workspace
if (pull_all)
names = fieldnames(s);
end
for i = 1:numel(names)
assignin('caller', names{i}, s.(names{i}));
end
end