tags:

views:

100

answers:

3

I wrote some function, that makes use of persistent variables, for example:

function y = integrator(x, t)
persistent yr; %result
...

and then, if I call it only once in a cycle, everything works fine:

x = integrator(x_dot, t);

but if I want to call it twice with different arguments, it will give wrong results:

x = integrator(x_dot, t);
y = integrator(y_dot, t);

This is not unexpected, but how can I deal with that? Use something different (non-persistent) variables or what?

I'm used to deal mostly with Simulink and the solution is not obvious to me.

A: 

You could just send and return the yr variable to the function each time. For your code above you would need to have a x_yr variable and a y_yr variable. It may not be very elegant, but it would work.

If you only want two instances of this function (as above with x and y) then you could make two functions that are identical except in name like xintegrator and yintegrator. Or, you could have yr be an array and have a parameter sent when calling integrator specifying which value in the array to use.

Justin Peel
+1  A: 

The best solution would change what you have to something like:

function [y, yr] = integrator(x, t, yr)
if nargin < 3
    yr = []; % will behave identically to persistent when yr is not given
end

Now you can make repeated calls as:

[x,xr] = integrator(x, t);
[x,xr] = integrator(x, t, xr);

[y,yr] = integrator(x, t);
[y,yr] = integrator(x, t, yr);

Though I wouldn't recommend it, there is a way to keep your current implementation and nearly achieve your desired result. It's possible to clear persistent variables by clearing the function. This will allow you to "reset" the persistent variable, which means this sequence of calls should work:

x = integrator(x_dot, t);
clear integrator;
y = integrator(y_dot, t);

But note that this will likely not produce the expected result when calling

x = integrator(x_dot, t);
clear integrator;
y = integrator(y_dot, t);
clear integrator;
x = integrator(x_dot, t);

Whereas in the solution I suggest first you can call

[x,xr] = integrator(x, t);
[y,yr] = integrator(x, t);
[x,xr] = integrator(x, t, xr);
[y,yr] = integrator(x, t, yr);

and the results will maintain state as expected.

Mark E
A: 

You could use a closure for this:

function integrator_handle = make_integrator(yr)

  function y = integrator(x, t)
    y = x + yr;
    yr = yr + 1;
  end

integrator_handle = @integrator; % (1)
end

To use:

>> integrator1 = make_integrator(0); % 0 is the initial value for yr
>> integrator2 = make_integrator(1);

integrator1 and integrator2 are now stateful function handles, essentially closures that have captured the state of yr as it was at the point where the function handle was created (the line marked with the comment "% (1)"). They can be invoked using parenthesis-indexing, which looks just like function invocation:

y = integrator1(x, t);

Any modifications to yr during the execution of the function handle will be retained with the function handle, so in my example above, yr will keep incrementing by one each time an integrator is called, but only for that particular instance of the integrator.

SCFrench

related questions