필터 지우기
필터 지우기

How to avoid using a global variable in this case

조회 수: 2 (최근 30일)
Patrick Mboma
Patrick Mboma 2013년 3월 26일
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
Walter Roberson
Walter Roberson 2013년 3월 26일
Is the counter to be per-class or per-object ?
Patrick Mboma
Patrick Mboma 2013년 3월 26일
the counter is per object. It is used, among other things, to keep track of the sequence of operations since the container does not order the entries according to their order of occurrence.

댓글을 달려면 로그인하십시오.

채택된 답변

Jan
Jan 2013년 3월 26일
편집: Jan 2013년 3월 26일
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
Jan
Jan 2013년 3월 26일
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.
Patrick Mboma
Patrick Mboma 2013년 3월 26일
편집: Patrick Mboma 2013년 3월 26일
Thank you very much Jan.
In your implementation, push will then become a static method, instead of public as it is currently the case in my code. While this does not solve all of my problems, but it definitely gets me one step further.

댓글을 달려면 로그인하십시오.

추가 답변 (1개)

Cedric
Cedric 2013년 3월 26일
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 =
{}
  댓글 수: 1
Patrick Mboma
Patrick Mboma 2013년 3월 26일
Hi Cedric, I am dealing with OOP, but what I need to keep track of is the sequence of all the operations done, not the operations done by each object.

댓글을 달려면 로그인하십시오.

카테고리

Help CenterFile Exchange에서 Software Development Tools에 대해 자세히 알아보기

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by