Search code examples
matlabfunctionreturn-valueworkspace

MATLAB: script vs function concerning output-argument


I have a script which might be aborted due to long runtime and continued later. Let's assume it looks a bit like this:

data = []; % can't preallocate as I don't know the number of entries yet here...
while(1)
   % ...
   data = [data; someNewEntry];
end

The good thing about it is that when running as a script, whenever I abort it, I have the variable data in te workspace.

But I wanted to convert it into a function because the script has quite a big amount of variables and clutters up my workspace with it. Let's assume I now converted it like this:

function data = myFnc()
data = []; % can't preallocate as I don't know the number of entries yet here...
while(1)
   % ...
   data = [data; someNewEntry];
end

Problem nnow is: When I abort the function, I'm losing all the entries in data which have been made to this point. How to solve this issue and make return the current vector data when aborting the function? The only possible solution I came up with was to use was something like this to use in the for-loop:

if(nargout == 1)
   assignin('caller','data', data);
end

But somehow I don't like this approach too much. But okay it seems alright to me. But one thing still annoys me about it: When using that I always assign the data to the workspace-var data as I don't know how to get the name of the output variable of the caller (i.e. bla = myFnc() -> it would be bla, thus assignin('caller','bla', data);). I know there is the matlab function inputnames() but I couldn't find the equivalent for the output vars. Thanks a lot in advance!


Solution

  • One solution might be to use global variables. Example with a simple counter:

    function data = myFnc()
    
    global data; % make it a global
    if isempty(data) % not yet initialized
        data = [];
    end
    
    i = 1;
    while(i < 10)
       pause(1)
       disp(i)
       data = [data, i];
       i = i + 1;
    end
    

    Then on the command line, you have to do global data once, and you can access the saved state. Quick test, I aborted the program with CTRL+C while it was running:

    >> clear
    >> clear global
    >> x = myFnc();
         1
         2
         3
         4
    Operation terminated by user during myFnc (line 10)
    >> x
    Undefined function or variable 'x'.
    >> data
    Undefined function or variable 'data'.
    >> global data
    >> data
    data =
         1     2     3     4
    

    The use of global variables is usually not recommended, but on occasion they can be useful. I sometimes use globals to cache an expensive calculation so that it only has to computed once for every time I launch Matlab:

    global data;
    if isempty(data)
        data = expensive_calculation();
    end
    

    For complex programs, there are probably cleaner ways to save some state from one iteration to another (implement some object?, pass a state object from one iteration to the next?, save to file?), but for some quick and dirty script, using globals is probably the easiest way.