Does it possible to use a function with persistent variables several times?
3 Ansichten (letzte 30 Tage)
Ältere Kommentare anzeigen
Alex Antipin
am 19 Feb. 2015
Kommentiert: Alex Antipin
am 24 Feb. 2015
I want to process several independent data arrays using a function which includes persistent variables in the following manner:
function cnt = example()
persistent cnt_p;
if isempty cnt_p
cnt_p = 0;
end
cnt=cnt_p;
cnt_p=cnt_p+1;
end
A = [1 2 3];
B = [4 5 6];
cnt1 = example(A(1));
cnt2 = example(B(1));
cnt1 = example(A(2));
cnt2 = example(B(2));
.....
Function saves variable cnt_p so result of this code will be: cnt1 = 3; cnt2 = 4;
But I want to see: cnt1 = 2; cnt2 = 2;
P.S. Of course I can simply create several copies of this function but it does not convenient.
0 Kommentare
Akzeptierte Antwort
Guillaume
am 19 Feb. 2015
Problem 1 is you're passing some arguments to example, yet your function doesn't take any argument. One would presume you'd want to do something with these arguments inside your function.
In any case, you need to think a bit more about what it is you want to do. I understand that you want your example function to keep track of the count independently if you call it with A as an argument or B as an argument.
The problem is that you don't actually call your example with A as an argument, or B as an argument, but with A(1) or B(1) or A(x) or X(y). Therefore, when the function call actually takes place, there is no more notion of A, B, X, it's just a number. You could of course keep track of different counts for different input numbers in your example function, but I don't think that's what you want?
If you wanted to keep a different count for different input numbers:
function count = countbynumber(number)
persistent m;
if isempty(m)
m = containers.Map('KeyType', 'double', 'ValueType', 'double');
end
if m.isKey(number)
count = m(number);
m(number) = m(number)+1;
else
count = 0;
m(number) = 1;
end
%do something with number ?
end
If you want to keep a different count for different name of input variable, you would have to call the function with:
c1 = countbyinputname(A);
c2 = countbyinputname(B);
c1 = countbyinputname(A);
c2 = countbyinputname(B);
That is you can't index the inputs. In which case the function itself is:
function count = countbynumber(v)
persistent m;
if isempty(m)
m = containers.Map('KeyType', 'char', 'ValueType', 'double');
end
varname = inputname(1);
if m.isKey(varname)
count = m(varname);
m(varname) = m(varname)+1;
else
count = 0;
m(varname) = 1;
end
%do something with v?
end
I'm not sure what would happen if you were to call the function with temporaries such as A(1).
But ultimately, the best solution may be to use a handle class for which you use different instances for different variables:
classdef counter < handle
properties (SetAccess = private)
count = 0;
end
methods
function count = increment(this, x)
count = this.count;
this.count = this.count+1;
%do something with x?
end
end
end
You'd use it like this:
counterA = counter;
counterB = counter;
c1 = counterA(A(1));
c2 = counterB(B(1));
c1 = counterA(A(2));
c2 = counterB(B(2));
3 Kommentare
Guillaume
am 19 Feb. 2015
Is it possible to save and then restore states of function with persistent variables? No, there's no such mechanism available.
But any of the options I've shown in my example would do what you want.
function result = my_filter(streamid, frame)
%streamid: a unique ID per stream, an integer here. You could use strings if you prefer
%frame: frame data
persistent mapid
if isempty(mapid)
mapid = containers.Map('KeyType', 'int32', 'ValueType', 'any');
end
if mapid.isKey(streamid)
%restore previous state:
state = mapid(streamid);
else
%create new state:
state = ????
end
%filter processing
%... done processing
%save state:
mapid(streamid) = currentstate;
end
And call the function with different ID for each stream:
r = my_filter(1, frame1(1)); %1st frame of 1st stream
r = my_filter(2, frame2(1)); %1st frame of 2nd stream
r = my_filter(1, frame1(2)); %2nd frame of 1st stream
r = my_filter(2, frame2(2)); etc.
classdef my_filter < handle
properties (SetAccess = private)
state;
end
methods
function this = my_filter(initialstate)
%constructor, possibly optional
this.state = initialstate;
end
function result = processframe(this, frame)
currentstate = this.state;
%process frame with currentstate
%...
this.state = currentstate;
end
end
end
And usage:
filterstream1 = myfilter(init1)
filterstream2 = myfilter(init2)
r = filterstream1(frame1(1)); %1st frame of 1st stream
r = filterstream2(frame2(1)); %1st frame of 2nd stream
%etc.
Finally, the last option is to for your filter to return its state, and accept a state as input. Then, it's down to the caller to read and write the state:
function [result, state] = myfilter(state, frame);
if isempty(state)
state = newstate;
end
%process frame using state
end
Usage:
[r, statestream1] = myfilter([], frame1(1));
[r, statestream2] = myfilter([], frame2(1));
[r, statestream1] = myfilter(statestream1, frame1(2));
[r, statestream2] = myfilter(statestream2, frame2(2));
Personally, I'd use classes for this.
Weitere Antworten (1)
Alessandro Masullo
am 19 Feb. 2015
If you want to clear the persistent variable you need to do it explicitly:
clear example
Siehe auch
Kategorien
Mehr zu Signal Generation, Manipulation, and Analysis finden Sie in Help Center und File Exchange
Produkte
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!