フィルターのクリア

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 Center および File ExchangeSoftware Development Tools についてさらに検索

Community Treasure Hunt

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

Start Hunting!

Translated by