Does anyone know if it\'s possible to have a stack of workspaces in MATLAB? It would be very convenient, to say the least.
I need this for research. We have several
Wonderful. (Haven't found using 0 with getappdata documented anywhere tho...so this could might away in the future.) Have added push & pop to my util library, and also the following:
pop_workspace(keep_current)
% keep_current: bool: if true, current vars retained after pop
. . .
if (~keep_current)
evalin('caller','clear');
end
A little creativity and one could retain only selected vars, and avoid overwriting on a pop. I found I also need the following function in my work:
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's variable,
% so modifying it will leave the stack's 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's workspace
if (pull_all)
names = fieldnames(s);
end
for i = 1:numel(names)
assignin('caller', names{i}, s.(names{i}));
end
end
The regular Matlab function call stack is itself a stack of workspaces. Just using functions is the easiest way to use one, and Matlab's copy-on-write makes this reasonably efficient. But that's probably not what you're asking.
There's a natural correspondence between workspaces and structs, since the same identifiers are valid for variable names and struct fields. They're both essentially identifier => Mxarray mappings.
You can use whos
and evalin
to capture workspace state to a struct. Use a cell vector to implement a stack of them. (A struct array won't work because it requires homogeneous field names.) The stack could be stored in appdata to prevent it from appearing in a workspace itself.
Here are push and pop functions for this technique.
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's workspace
names = fieldnames(s);
for i = 1:numel(names)
assignin('caller', names{i}, s.(names{i}));
end
It sounds like you'd like to switch back and forth between workspaces of variables. The best way I can think to do this is to use the SAVE, CLEAR, and LOAD commands to move sets of variables back and forth between MAT-files and the workspace:
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