[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

robust-iterator; detaching observers automaticly ?

Simon Strandgaard

10/3/2003 10:05:00 AM

I am working on a Robust-Iterator (tm).. where the iterators
gets registerd at the data-structure they traverse.
When doing insert/remove in the data-structure, then the iterators
still points to the same element.
Clone such an iterator will add an extra observer to the list.

What I cannot figure out is how to detach observers when an iterator is no
longer used.. kind of similar to the Ruby-destructor problem.

Question#1: should I introduce a #close method in all my object ?

Question#2: how do you unregister objects (pseudo automaticly) ?

--
Simon Strandgaard



server> cat robust.rb
require 'iterator'
require 'observer'

# purpose:
# a array with robust iterators
#
# functions:
# * iterators keeps pointing to the same element,
# when doing insert/remove (primary feature).
# * normal array behavier.
#
# issues:
# * you must #detach allocated iterators.
class RobustArray
# purpose:
# a robust iterator, which keeps its position
# even though you insert/remove elements.
#
# functions:
# * in case of changes in the array the iterator
# gets notify from the parent about the change.
# * #clone attaches the new instance to the parent.
#
# todo:
# * policies for how the iterator should behave
# detach_on_remove, prev_on_remove, next_on_remove
class Iterator < Iterator::Collection
def initialize(data)
super(data)
@data.add_observer(self)
end
def clone
instance = super
@data.add_observer(instance)
instance
end
def detach
@data.delete_observer(self)
@data = nil
@position = nil
end
def update(where, delta)
if delta > 0
if @position >= where
@position += delta
end
elsif (where+delta..where).member?(@position)
detach # remove ourselves from the iterator list
elsif @position >= where
@position += delta - 1
end
end
end

include Observable
def initialize(ary)
@data = ary
end
def to_a
@data
end
def size
@data.size
end
def [](index)
@data[index]
end
def []=(index, value)
@data[index] = value
end
def RobustArray.build_from_array(ary)
RobustArray.new(ary)
end
def create_iterator
Iterator.new(self)
end
def remove(range)
res = @data.slice!(range)
a = range.first
b = range.last
changed
notify_observers(b, -(b-a))
RobustArray.build_from_array(res)
end
def insert(where, data)
ary = data.to_a
@data[where, 0] = ary
changed
notify_observers(where, ary.size)
end
end
server>
2 Answers

elbows

10/3/2003 3:58:00 PM

0

You could use a block, a la File.open {}:
robust_array.create_iterator { |i|
do some stuff with the iterator...
}

Where the iterator is created and passed to the block, and then
detached after the block is executed.

or even

robust_array.each { |x| ... }
where the each is implemented with a robust iterator.

Neither of these solves the clone problem, but it at least makes
things easy in the common case.

Nathan

Simon Strandgaard <qj5nd7l02@sneakemail.com> wrote in message news:<pan.2003.10.03.10.05.25.997486@sneakemail.com>...
> I am working on a Robust-Iterator (tm).. where the iterators
> gets registerd at the data-structure they traverse.
> When doing insert/remove in the data-structure, then the iterators
> still points to the same element.
> Clone such an iterator will add an extra observer to the list.
>
> What I cannot figure out is how to detach observers when an iterator is no
> longer used.. kind of similar to the Ruby-destructor problem.
>
> Question#1: should I introduce a #close method in all my object ?
>
> Question#2: how do you unregister objects (pseudo automaticly) ?
>
> --
> Simon Strandgaard
>
>
>
> server> cat robust.rb
> require 'iterator'
> require 'observer'
>
> # purpose:
> # a array with robust iterators
> #
> # functions:
> # * iterators keeps pointing to the same element,
> # when doing insert/remove (primary feature).
> # * normal array behavier.
> #
> # issues:
> # * you must #detach allocated iterators.
> class RobustArray
> # purpose:
> # a robust iterator, which keeps its position
> # even though you insert/remove elements.
> #
> # functions:
> # * in case of changes in the array the iterator
> # gets notify from the parent about the change.
> # * #clone attaches the new instance to the parent.
> #
> # todo:
> # * policies for how the iterator should behave
> # detach_on_remove, prev_on_remove, next_on_remove
> class Iterator < Iterator::Collection
> def initialize(data)
> super(data)
> @data.add_observer(self)
> end
> def clone
> instance = super
> @data.add_observer(instance)
> instance
> end
> def detach
> @data.delete_observer(self)
> @data = nil
> @position = nil
> end
> def update(where, delta)
> if delta > 0
> if @position >= where
> @position += delta
> end
> elsif (where+delta..where).member?(@position)
> detach # remove ourselves from the iterator list
> elsif @position >= where
> @position += delta - 1
> end
> end
> end
>
> include Observable
> def initialize(ary)
> @data = ary
> end
> def to_a
> @data
> end
> def size
> @data.size
> end
> def [](index)
> @data[index]
> end
> def []=(index, value)
> @data[index] = value
> end
> def RobustArray.build_from_array(ary)
> RobustArray.new(ary)
> end
> def create_iterator
> Iterator.new(self)
> end
> def remove(range)
> res = @data.slice!(range)
> a = range.first
> b = range.last
> changed
> notify_observers(b, -(b-a))
> RobustArray.build_from_array(res)
> end
> def insert(where, data)
> ary = data.to_a
> @data[where, 0] = ary
> changed
> notify_observers(where, ary.size)
> end
> end
> server>

Simon Strandgaard

10/4/2003 9:32:00 PM

0

> Simon Strandgaard <qj5nd7l02@sneakemail.com> wrote in message news:<pan.2003.10.03.10.05.25.997486@sneakemail.com>...
>> I am working on a Robust-Iterator (tm).. where the iterators
>> gets registerd at the data-structure they traverse.
>> When doing insert/remove in the data-structure, then the iterators
>> still points to the same element.
>> Clone such an iterator will add an extra observer to the list.
>>
>> What I cannot figure out is how to detach observers when an iterator is no
>> longer used.. kind of similar to the Ruby-destructor problem.
>>
>> Question#1: should I introduce a #close method in all my object ?
>>
>> Question#2: how do you unregister objects (pseudo automaticly) ?


On Fri, 03 Oct 2003 09:57:47 -0700, Nathan Weston wrote:
> You could use a block, a la File.open {}:
> robust_array.create_iterator { |i|
> do some stuff with the iterator...
> }
>
> Where the iterator is created and passed to the block, and then
> detached after the block is executed.
>
> or even
>
> robust_array.each { |x| ... }
> where the each is implemented with a robust iterator.

My problem is that I want to build other kinds of iterators
using robust-iterator. For instance I have a Iterator::Range which
is created with a first and a last iterator, which may be a
robust-iterator. The #each operation is not used there at all,
the Iterator::Range exercises #is_done? and #next.


> Neither of these solves the clone problem, but it at least makes
> things easy in the common case.

True, I am C++brainwashed, well knowing that destructors cannot help me
here. But I hesitate too much implementing #close and &blocks in the whole
class hierarchy.

I was hoping that others had knowledge about #clone and how to automaticly
unregister instances when they are no longer in usage. If there are
any rubists which has such knowledge, then say something :-)

--
Simon Strandgaard

BTW: If you want to see the source for robust-array, you can do it here:
http://rubyforge.org/cgi-bin/cvsweb.cgi/projects/experimental/iterator2/?cvsro...