```> From: Benjamin J. Tilly [mailto:ben_tilly / operamail.com]
[...]
> Why would you expect u to be != to s?
Because I am moron (you should realize by
know that can't distinguish between +/- ;-)
but I realized this when pressed the send
button - to late ...

> The result looks very reasonable to me.
>
> If s == t and t == u, then transitivity would require
> that s == u and in this example that is exactly what
> happens!!!
[...]
> I remain unconvinced that this scheme stinks.
Because it breaks current code - big time

p ([1,] == [1,[1,])  # => false current ruby

p ([1,] == [1,[1,])  # => true with Ben's id caching

(this is with your script I re-attached to make
sure that there is no confusion ). Actually my
version of id-caching never had this problem
but I still don't like it because a lot of things
in ruby actually depend on the equality notion of
arrays (you use this constantly even when your not
aware of this).
Right now at least the interpreter is crashing -
if a dubious equality notion is introduced some
scriot will produce garbage because RCO violate
basic Container axioms (and you know this as well
as I do).

The basic problem is the following - lets say

a = ; a <<a
b = ; bm =; b << bm;  bm << b;

then with any id-caching you will get
p  a== b  # => true

From this you cleverly conclude that if set

a = 2; b  = 2

then  ``a == b'' right?  - but wrong with
id-caching - admittedly Ruby has a lot of side
effects but to support something like this is
just nonsense IMHO.

> >> The problem is that this looks like:
> >>
> >>     a == c == [[[[...], 2], 1], 2], 1]
> >>
> >> and
> >>
> >>     b == d == [[[[...], 1], 2], 1], 2]
> >
> >it is actually a fun problem to construct
> >these two arrays
> >
> In what you cut out I did construct them I thought.
I know - I was thinking of [[[..],2],1]

> >>
>
> I strongly disbelieve that there is any answer in this
> case that gives an answer you can argue is reasonable.
> makes sense.  But Ruby's existing behaviour is depth first,
> and with depth first the answer that you get depends upon
> how far down you go before breaking the recursion.

Okay I don't want to introduce such a comparison if both
sides are ``tangled'' but if you untangle the loops you
can compare them as normal arrays - all the axioms
would be satisfied (you have to use a version which is
non-destructive because the left hand side and right
side could be ``inter-tangled'' and you don't want to
destroy your original RCO even so they deserve it;-)
But tangled bases comparison as also side-effect problem

[...]
Christoph

I only added three ``\'' at the ? to make it work ...
-----------------
true
true
-----------------
require 'Ben'
def cl( a, n)
base=loop= [a.clone]
(n-1).times { tmp = [a.clone]; loop << tmp; loop = tmp }
loop << base
base
end

p (cl("a",1) == cl("a",101))  # all id-cachings have this problem
p ([1,] == [1,[1,]])
-----------------
class Object
def  eq? (other, cache)
id == other.id ? \
true :
self == other
end

def cmp (other, cache)
id == other.id ? \
0 :
self <=> other
end
end

class SeenCache
attr :seen

def initialize
@seen = Hash.new nil
end

def visited? (this, that)
if @seen[this].nil?
@seen[this] = [ that ]
else
return true if @seen[this].include? that
@seen[this].push that
end
false
end

end

class Array
def <=> (other)
cmp(other, SeenCache.new)
end

def cmp (other, cache)
if (id == other.id or cache.visited? (id, other.id))
return 0
else
other_a = other.to_ary
min = length < other_a.length ? \
length :
other_a.length
for i in 0..(min - 1)
val = self[i].cmp(other[i], cache)
return val unless val == 0
end
length <=> other_a.length
end
end

def == (other)
eq? (other, SeenCache.new)
end

def eq? (other, cache)
if (other.kind_of? (Array) and length == other.length)
if (id != other.id and not cache.visited? (id, other.id))
for i in 0...(length - 1) do
return false unless self[i].eq? (other[i], cache)
end
end
return true
else
return false
end
end

end

```