From: Sean O'Dell Date: 2003-10-02T02:31:19+09:00 Subject: Re: Making == symmetric? Nathan Weston wrote: > It has always bothered me that == is not symmetric in ruby: > a == b is shorthand for a.==(b), while b == a is shorthand for > b.==(a), and a and b might not agree on whether they are equal. My own opinion on this is: == is like asking one object if it's equal to another. I know that particular operator is supposed to provide a balanced equality test, but I only thought of == that way early in my programming career; that notion has long since been replaced with the notion that one side is asking if the other side is equal, and switching things around will yield different results. Because of this, the way Ruby handles == always made perfect sense to me. But it would be nice to have a way to perform a perfectly symmetrical balanced test. Perhaps a solution would be to create a module that overrides == and adds ==? to some or all classes. The ==? operator can return true, false or nil. Nil would mean the method isn't really an authority. The overridden == method can try the ==? method for both objects. If one or both ==? methods return true or false, that's the answer. If both return different, non-nil answers, an exception can be thrown. If both return nil, then the super == method can be called to alert you that both objects consider themselves an authority, but they are not returning the same result. Example: class Object def ==?(comparator) return nil end def ==(comparate) left = ==?(comparate) right = comparate.==?(self) if (left == nil and right == nil) then return super elsif (left == right) return left and right ? true : false elseif (left == nil) return right elseif (right == nil) return left else raise "both comparates return unbalanced equality tests" end end class String def ==?(comparate) return self.to_s == comparate.to_s if (comparate.class == Number) return super end end class Number def ==?(comparate) return self.to_s == comparate if (comparate.class == String) return super end end Clearly this is something that ought to be written in C, not Ruby, for speed purposes, but the idea seems right to me. Everything can even be kept in one module, expressly for the purpose of include'ing when needed, so this sort of implementation wouldn't break existing code. Sean O'Dell