Zakaria wrote:
....
>
> URL? I know I'm lazy
Also checkout [ruby-talk :48114] (+ google) and
http://www.rubygarden.org/ruby?CompareByValue.
Personally I would tend to implement such a
class as a subclass of a Struct class ...
class LoopTag < Struct.new(

aram,:contents)
def initialize(param)
super(param,[])
end
...
end
Just for the heck of it here is a cleaned up version
of the same problem I wrote two years ago, which is
sort (of) recursion and thread safe. There is an
obvious similarity to the idea of Joel content method
returning a Hash.
---
module CompareByValue
def ==(other)
if not instance_of?(other.class)
false
elsif equal?(other)
true
elsif id < other.id
CompareByValue.comp?(self,other)
else
CompareByValue.comp?(other,self)
end
end
end
class << CompareByValue
class Seen < Hash
Pair = Struct.new(:l,:r)
def initialize(l,r)
store(Pair.new(l.id,r.id),true)
end
def seen?(l,r)
self[Pair.new(l.id,r.id)]
end
def default(key)
store(key,true)
nil
end
def remove(l,r)
delete Pair.new(l.id,r.id)
end
end
# symbol mangling
SEEN_COMPS = "CBV#{id}_comps".intern
NUMS_CALLS = "CBV#{id}_calls".intern
def comp?(l,r)
return true if thread_local_seen?(l,r)
begin
Thread.current[NUMS_CALLS] +=1
return Comp.new.comp?(l,r)
rescue
Thread.current[SEEN_COMPS].remove(l,r)
raise
ensure
if (Thread.current[NUMS_CALLS] -= 1).zero?
Thread.current[SEEN_COMPS].clear
end
end
end
def thread_local_seen?(l,r)
unless comps = Thread.current[SEEN_COMPS]
Thread.current[NUMS_CALLS] = 0
Thread.current[SEEN_COMPS] = Seen.new(l,r)
false
else
comps.seen?(l,r)
end
end
class Comp < Hash
def comp?(l,r)
return true if l.equal?(r)
vars = l.instance_variables.sort!
return false unless vars == r.instance_variables.sort!
store(l.id,r.id)
vars.each do |name|
ll = l.instance_eval(name)
rr = r.instance_eval(name)
if CompareByValue === ll
return false unless ll.instance_of?(rr.class)
if rr_seen_id = self[ll.id]
return false unless rr_seen_id == rr.id
else
return false unless comp?(ll,rr)
end
else
return false unless ll == rr
end
end
return true
end
end
end
---
/Christoph