How to avoid using a global variable in this case
1 view (last 30 days)
Show older comments
Dear all,
I have the following problem. I wrote some code where I overload various operators (+ - * /) and I would like to keep track of all the operations done. I initialize a session by creating a global variable, "myglobal", which will help me in this endeavor.
global myglobal
myglobal=containers.Map();
Then the typical overloaded operation does the following
function c=plus(a,b)
c=myobject(a.x+b.x);
push(c)
end
where the push function above roughly looks like this
function push(c)
global myglobal
Count=myglobal.Count+1;
myglobal(Count)=c.x;
end
I know using global variables is bad and I would like to get rid of the global variable. Any suggestion on how to go about this?
Thanks,
Pat.
2 Comments
Accepted Answer
Jan
on 26 Mar 2013
Edited: Jan
on 26 Mar 2013
Use a persistent variable instead:
function Reply = push(c)
persistent myCollector
if isempty(myCollector)
myCollector.Count = 0;
myCollector.Data = cell(1, 1000); % Pre-allocate
end
% Reply the local collector and reset it:
if nargin == 0
myCollector.Data = myCollector.Data(1:myCollector.Count); % Crop
Reply = myCollector;
myCollector = [];
return;
end
count = myCollector.Count+1;
myCollector.Data{count} = c.x;
myCollector.Count = count;
% Re-allocate on demand:
if length(myCollector.Data) == count;
myCollector.Data{count + 1000} = [];
end
end
This reduces the bad effects of letting the data cell grow in each iteration. The data are not stored globally, where any function can overwrite the values accidently. The value of the collector can be checked easily by the debugger in opposite to globals. And you can get the results by:
collector = push();
[EDITED] But when you look at this code, the persistenmt variable is actually a static member of an object oriented approach. When you do some oop already, it would be cleaner to implement this as further object also.
3 Comments
Jan
on 26 Mar 2013
I have a non-oop (but oo-design) code, which stores a list of "channels" to write text to. A "channel" can be a file, the command window or a GUI-element. Similar to the posted function, I can either manipulate the persistently store list of "channels" or output strings. Instead of using push() you could use a 2nd input to recognize commands to manipulate the collector variable:
function Reply = push(in1, in2)
persistent C
if isempty(C)
% initialize ...
end
% Process meta-commands "push(Command, Data)":
if nargin == 2
switch Command
case 'get'
Reply = C;
case 'reset'
C = [];
case 'append' % Append new values:
C.Data = cat(2, C.Data(1:C.Count), in2, cell(1,1000));
C.Count = C.Count + length(in2);
otherwise
error('Unknown command: %s', in1);
end
return;
end
% Normal processing of "push(x)":
...
end
Then the persistent data are static private data, while there are private functions to access them also.
You see, that the complexity of the function is growing rapidly. And a slightly modified version (perhaps stacks for operations with 1, 2 or 3 arguments) would demand for copying the complete code, such that a later maintenance gets more and more complicated. Therefore I recommend this approach only, if there are reasons to avoid OOP, e.g. backward compatibility.
More Answers (1)
Cedric
on 26 Mar 2013
I thought that you were talking about OOP with your initial question, but if not, it is not a good idea to overload common operators.
A handle class would certainly make everything easier.. e.g.
classdef MBoma < handle
properties
value
history = {}
end
methods
function self = MBoma(value)
self.value = value ;
end
function c = plus(self, b)
if isa(b, 'MBoma')
c = MBoma(self.value + b.value) ;
self.push('plus', b.value) ;
b.push('plus', self.value) ;
else
c = self.value + b ;
self.push('plus', b) ;
end
end
function push(self, id, value)
self.history = [self.history; {id, value}] ;
end
end
end
With that,
>> a = MBoma(5) ;
>> b = MBoma(7) ;
>> c = a + 9
c =
14
>> d = a + b
d = MBoma handle
Properties:
value: 12
history: {}
>> a.history
ans =
'plus' [9]
'plus' [7]
>> b.history
ans =
'plus' [5]
>> d.history
ans =
{}
See Also
Categories
Find more on Software Development Tools in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!