Question

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!

Was it helpful?

Solution 2

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.

OTHER TIPS

I can think of 2 recommended solutions:

1. Interrupt the function without losing the workspace

As I described here, this should not be a problem if you always switch on

`dbstop if error`

2. Frequently save your variables

With your assignin solution you already came close, as it 'saves' the variable to the base workspace. However this is still not a very safe space to store variables. Therfore I would recommend saving them with:

save data data

If the second option is too much of a performance killer you can just do it every 1000 iterations or so.

One other option is to use a MATLAB reference-type variable. For example, you could use a containers.Map, like this:

m = containers.Map();
myFcn(m);
% Later, after hitting CTRL-C
m('data') % get latest value

with a function like this:

function myFcn(map)
data = [];
while true
    data = [data, rand()];
    map('data') = data;
end
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top