[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

selfassignment and close

Simon Strandgaard

11/28/2003 7:25:00 PM

I would like to overload the '+=' operator. But it doesn't seems to be
possible? If it isn't possible, then how to use the '+' operator and at
the same time get the instance #closed correctly ?


server> ruby a.rb
open 42
open 43
close 42
close 43
-----------------------
open 42
open 43
close 43
server> expand -t2 a.rb
class Iterator
def initialize(value)
@value = value
puts "open #{@value}"
end
def close
puts "close #{@value}"
end
def +(n)
self.class.new(@value + n)
end
end

a = Iterator.new(42)
b = a + 1
a.close
b.close

puts "-----------------------"

a = Iterator.new(42)
a += 1 # Question: How to do selfassignment ?
a.close
# 42 never gets closed!
server>


--
Simon Strandgaard
7 Answers

Hal E. Fulton

11/28/2003 7:48:00 PM

0

Simon Strandgaard wrote:
> a = Iterator.new(42)
> a += 1 # Question: How to do selfassignment ?
> a.close
> # 42 never gets closed!

What's happening here is that += is dependent on +, yet it is still
an assignment.

a += 1 is equivalent to a=a+1; so as you can see, a new object is
created and assigned to a.

You could always implement methods like succ or add that would
change the value without changing the object's identity.

For an analogy with strings and arrays, these have a #replace
method that will change all the contents without changing the
object's identity.

Or an append can be done with << on either of these also.

But = or += (with a nontrivial expression) would create new objects:

x = "abc"
y = [1,2,3]
def x.foo
puts "The string #{self} has a singleton"
end
def y.foo
puts "The array #{self} also has a singleton"
end

x.foo # The string abc has a singleton
y.foo # The array 123 also...
x << "def"
y << [4,5,6]
x.foo # The string abcdef has a ...
y.foo # The array 123456 has...

x += "ghi"
y += [7,8,9]
x.foo # Error
y.foo # would also be an error

Does this clarify any?

Hal


Simon Strandgaard

11/28/2003 8:01:00 PM

0

On Sat, 29 Nov 2003 04:47:37 +0900, Hal Fulton wrote:

> Simon Strandgaard wrote:
>> a = Iterator.new(42)
>> a += 1 # Question: How to do selfassignment ?
>> a.close
>> # 42 never gets closed!
>
> What's happening here is that += is dependent on +, yet it is still
> an assignment.
>
> a += 1 is equivalent to a=a+1; so as you can see, a new object is
> created and assigned to a.

I know that. What I don't know, are if there are any tricks when dealing
with '+=' ?


> You could always implement methods like succ or add that would
> change the value without changing the object's identity.

Yes I already have #next and #prev.


> Does this clarify any?

Conclusion: providing a PLUS ('+') operator, can be dangerous because the
user can invoke '+=' and the instance will not get #closed correctly.
safer to undef '+'.

--
Simon Strandgaard

Ara.T.Howard

11/28/2003 9:55:00 PM

0

Simon Strandgaard

11/30/2003 5:17:00 PM

0

On Fri, 28 Nov 2003 14:54:59 -0700, Ara.T.Howard wrote:

> On Fri, 28 Nov 2003, Simon Strandgaard wrote:
>> I would like to overload the '+=' operator. But it doesn't seems to be
>> possible? If it isn't possible, then how to use the '+' operator and at
>> the same time get the instance #closed correctly ?
[snip code]
>
> if you rely on ObjectSpace.define_finalizer you don't really know when the
> call will be made, but perhaps something using it would be better... this
> would cause an apparent 'leak' in long running programs. the general idea -
> track objects within the class itself and make sure to free them - should be
> workable for you though.

I had something similar, a WrapperIterator which kept track of all clones.
When the operation were completed, I could then sweep them.
But I don't consider it as a 'real' solution :-)

It has to be solved _correct_, before im satisfied.

--
Simon Strandgaard



server> expand -t2 wrapper_close.rb
require 'iterator' # http://raa.ruby-lang.org/list.rhtml?nam...

class Scanner
def initialize(iterator)
@iterator = iterator
end
def execute
a = @iterator.clone
b = @iterator.clone
c = @iterator.clone
d = @iterator.clone
end
end

# keep track of how many instances we have
class CountingIterator < Iterator::Collection
@@count = 0
def clone
@@count += 1
super()
end
def self.count; @@count end
def close
@@count -= 1
super()
end
end

class WrapperIterator < Iterator::Base
def initialize(iterator, stack=nil)
@iterator = iterator
@stack = stack || []
end
def clone
i = @iterator.clone
@stack << i
WrapperIterator.new(@iterator, @stack)
end
def close
@stack.map{|i| i.close; nil}
end
end

ary = (0..19).to_a
iterator = CountingIterator.new(ary)
#wrap_iterator = iterator
wrap_iterator = WrapperIterator.new(iterator)
s = Scanner.new(wrap_iterator)
s.execute
p CountingIterator.count
wrap_iterator.close # ensure all iterators gets closed
p CountingIterator.count
server> ruby wrapper_close.rb
4
0
server>

Robert Klemme

12/1/2003 7:57:00 AM

0


"Simon Strandgaard" <neoneye@adslhome.dk> schrieb im Newsbeitrag
news:pan.2003.11.28.20.00.51.850573@adslhome.dk...
> On Sat, 29 Nov 2003 04:47:37 +0900, Hal Fulton wrote:
>
> > Simon Strandgaard wrote:
> >> a = Iterator.new(42)
> >> a += 1 # Question: How to do selfassignment ?
> >> a.close
> >> # 42 never gets closed!
> >
> > What's happening here is that += is dependent on +, yet it is still
> > an assignment.
> >
> > a += 1 is equivalent to a=a+1; so as you can see, a new object is
> > created and assigned to a.
>
> I know that. What I don't know, are if there are any tricks when dealing
> with '+=' ?
>
>
> > You could always implement methods like succ or add that would
> > change the value without changing the object's identity.
>
> Yes I already have #next and #prev.
>
>
> > Does this clarify any?
>
> Conclusion: providing a PLUS ('+') operator, can be dangerous because
the
> user can invoke '+=' and the instance will not get #closed correctly.
> safer to undef '+'.

IMHO "+" carries the wrong semantics for an iterator in Ruby: you don't
want a new object to be created, instead you want the iterator to change
its state.

If you want to provide numeric updates, why not just define succ like
this:

def succ(inc=1) ... end

Regards

robert

Simon Strandgaard

12/1/2003 2:04:00 PM

0

On Mon, 01 Dec 2003 08:57:26 +0100, Robert Klemme wrote:
[snip]
> If you want to provide numeric updates, why not just define succ like
> this:
>
> def succ(inc=1) ... end


Its already defined like this:


# move <i>n</i> steps forward
def next(n=1)
n.times { self.next1 }
self
end

# move <i>n</i> steps backwards
def prev(n=1)
n.times { self.prev1 }
self
end


Thanks anyway :-)

--
Simon Strandgaard

Robert Klemme

12/1/2003 3:13:00 PM

0


"Simon Strandgaard" <neoneye@adslhome.dk> schrieb im Newsbeitrag
news:pan.2003.12.01.14.03.56.882810@adslhome.dk...
> On Mon, 01 Dec 2003 08:57:26 +0100, Robert Klemme wrote:
> [snip]
> > If you want to provide numeric updates, why not just define succ like
> > this:
> >
> > def succ(inc=1) ... end
>
>
> Its already defined like this:

Great! So you read my mind even before I could. :-)

> Thanks anyway :-)

You're welcome! :-)

robert