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 ?
ruby a.rb
open 42
open 43
close 42
close 43
···
open 42
open 43
close 43
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
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
class Iterator
class << self
def objs; @objs ||= ; end
def reap; objs.each{|obj| obj.close}; end
def new(*args,&block); objs << (obj = super); obj; end
at_exit { Iterator.reap }
end
def initialize(value) @value = value
puts “open #{@value}”
end
def close
puts “close #{@value}” unless @closed @closed = true
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!
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.
food for thought…
-a
···
On Fri, 28 Nov 2003, Simon Strandgaard wrote:
Date: Fri, 28 Nov 2003 20:24:58 +0100
From: Simon Strandgaard neoneye@adslhome.dk
Newsgroups: comp.lang.ruby
Subject: selfassignment and close
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 ?
ruby a.rb
open 42
open 43
close 42
close 43
open 42
open 43
close 43
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!
–
ATTN: please update your address books with address below!
The difference between art and science is that science is what we
understand well enough to explain to a computer.
Art is everything else.
– Donald Knuth, “Discover”
/bin/sh -c ‘for l in ruby perl;do $l -e “print "\x3a\x2d\x29\x0a"”;done’
===============================================================================
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 ‘+’.
···
On Sat, 29 Nov 2003 04:47:37 +0900, Hal Fulton 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.
···
On Fri, 28 Nov 2003 14:54:59 -0700, Ara.T.Howard wrote:
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
“Simon Strandgaard” neoneye@adslhome.dk schrieb im Newsbeitrag
news:pan.2003.11.28.20.00.51.850573@adslhome.dk…
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
···
On Sat, 29 Nov 2003 04:47:37 +0900, Hal Fulton wrote: