> From: ts [mailto:decoux / moulon.inra.fr] > >>>>> "M" == Mathieu Bouchard <matju / sympatico.ca> writes: > > > M> def f(x); [x,x]; end > M> def g(x); f f f f f f f f x; end > M> (g g g 1) == (g g g 1) #=> true > > Try this > > def f(x); [x,x]; end > def g(x); f f f f f f f f x; end > p (g g g 1) > Object (in)equality is an extremely subtle issue (un-decidable for any half way expressive semantics, never mind thread safety, persistence etc. ) and Ruby's untyped functions don't make things easier - on the other hand Matju's example is perfectly legitimate (non abusive) and any Array (in)equality algorithm should be able to handle it (very few objects are created.) I came up with following simple minded band-aid do handle Array (in)equality (I don't even want think about Hashes right now ). Unfortunately this requires some minor changes to the language itself - i.e. consider this as a RCR request (this is a request for a general direction - I am not hung up on names and I won't hold my breath that something like this will be excepted;-) Christoph. Ps. The example will probably flake out on windows (not on mine so) ... ----------------------------------- $ ruby -w Untangle.rb Untangle.rb:22: warning: push (...) interpreted as method call Untangle.rb:25: warning: include? (...) interpreted as method call Untangle.rb:51: warning: untangled_equal? (...) interpreted as method call Untangle.rb:60: warning: untangled_equal? (...) interpreted as method call Untangle.rb:68: warning: p (...) interpreted as method call Untangle.rb:69: warning: p (...) interpreted as method call Untangle.rb:82: warning: p (...) interpreted as method call Untangle.rb:110: warning: untangled_equal? (...) interpreted as method call Untangle.rb:59: warning: discarding old == true false [3] [1, 2, 3, [...], [...]] [1, 2, [...], [1, 2, 3, [...], [...]]] true true false ----------------------------------- class Object ########################## # In general just ignore the bag ########################## def untangled_equal? (other, bag) self == other end end class IdBag ########################## # probably this class should also # help im mangeging exceptions # and bag individual id's to aid # un_tangled flatten!, hashing etc. ########################## def initialize @bag = [] end def include_pair a, b @bag.push (a+ b << Fixnum::Maxlog) end def included_pair? a,b @bag.include? (a+ b << Fixnum::Maxlog) end private ########################## # Since there is no Limits ... # change this depending on # your maschine ########################## class Fixnum Maxlog = 32 end end ########################## class Array def untangled_equal? (other,id_bag) # sanety checks return false unless other.kind_of? Array return false unless length == other.length # bag the current id's and check # if id's match id_bag.include_pair id, other.id return true if id == other.id each_index do |i| next if id_bag.included_pair? \ self[i].id, other[i].id if self[i].untangled_equal? \ (other[i], id_bag) next else return false end end return true end def == (other) untangled_equal? (other, IdBag.new ) end end ########################## # Examples ########################## p ([1,3,3,[3,4],"a"] == [1,3,3,[3,4],"a"]) p ([1,3,3,[3,4],"a"] == [1,3,3,[3,4],"b"]) ########################## a =[1,2,3]; a << a; b =[1,2]; b << b; a << a; b << a; p a - b; p a; p b ########################## def f(x); [x,x]; end def g(x); f f f f f f f f x; end def h(x); g g g g g g g g x; end def i(x); h h h h h h h h x; end def j(x); i i i i i i i x;end p (j(1) == j(1)) ########################## # Integrate your own class in # untangle_equal? scheme ... ########################## class UnOrderedPair def untangled_equal?(other,id_bag) return false unless other.kind_of? UnOrderedPair return true if id == other.id # different bag startegy ... id_bag.include_pair id, other.id id_bag.include_pair other.id, id # ..... return true if id == other.id return true if \ ( @l.untangled_equal?(other.l, id_bag) ) && \ ( @r.untangled_equal?(other.r, id_bag) ) return true if \ ( @l.untangled_equal?(other.r, id_bag) ) && \ ( @r.untangled_equal?(other.l, id_bag) ) return false end def == (other) untangled_equal? (other, IdBag.new ) end def initialize(ll,rr) @l = ll; @r = rr end protected attr_reader :l, :r end ########################## # Examples ########################## l = [3,2,3]; r=[3,2] pl = UnOrderedPair.new l,r pr = UnOrderedPair.new r,l l << pl; r << pr p pl == pr ########################## pl = UnOrderedPair.new l,r pr = UnOrderedPair.new r,r l << pl; r << pr p pl == pr