Is there a way to push a MATLAB workspace onto a stack?

我们两清 提交于 2019-11-27 01:23:35

问题


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 scripts which interact in interesting ways. Functions have local variables, but not scripts...


回答1:


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



回答2:


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



回答3:


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


来源:https://stackoverflow.com/questions/1823668/is-there-a-way-to-push-a-matlab-workspace-onto-a-stack

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!