From: David Simmons Date: 2001-10-24T12:08:38+09:00 Subject: [ruby-talk:23138] Re: Overriding #== [numeric operators; hashing and comparison; binary selectors] "Dave Harris" wrote in message news:memo.20011023221644.53147H@brangdon.madasafish.com... > chris.uppal@metagnostic.REMOVE-THIS.org (Chris Uppal) wrote (abridged): > > > If #== is a MOP message like #basicAt: or #class, we shouldn't be > > > using it so freely. > > > > That's it exactly. > > Agreed for immutable objects. However, I would have thought it was > legitimate to test whether two mutable objects are the same object. > Equality is not always enough. > > Even when #= is defined to return the same result as #==, there are times > when using #= feels wrong to me. Eg: > > kiss: aPerson > aPerson = self wife > ifFalse: [^aPerson slapFace]. > "..." > > I don't want someone equivalent to my wife, I want my wife. When I originally designed QKS Smalltalk, I distinguished the notions of equality (#=) from equivalence (#=~) (and continued to do so in designing SmallScript). [specifically looking at equivalence for use in case-insensitive character comparisons] ------- SIDEBAR ------- #=~ can be read as equals-approximately. Unfortunately, the #~= message was define in Smalltalk for not-equal (unlike any other language). In SmallScript this (deprecated form) is an alias for the #!= message. And similarly for #~~ for #!==. ----------- END SIDEBAR ----------- I think it is accurate/correct [for any Smalltalk implementation/the Smalltalk language] to say that identity (#==) will uniquely identify "an object instance" for any class that is not provided as part of a base/core implementation. I suggest, taking it from SmallScript, that object-equivalence #(==~) is what you are looking for. Sigh... I just read someone's c.l.s. post (Peter Van Rooijen) who said that Cincom VW still only supports a max of two-char binary selectors. I thought we solved/addressed this issue during the ANSI x3j20 process. ------------------------------------ SIDEBAR Unicode in binary selectors: ------------------------------------ QKS Smalltalk had no binary selector character limits and allowed any unicode symbol to be used in declaring a binary selector. SmallScript also allows any number of unicode symbol characters but the current build does not have full unicode/code-page services integrated into the compiler/literal-manager. ----------- END SIDEBAR ----------- Whereas #(=) is querying about value equality when used to refer to numeric objects. Unfortunately, these notions of "value" versus "representation/manifestation" are not clearly distinguished/defined within Smalltalk. This is a direct result of not clearly defining the language vs the frameworks. I.e., the philosophy that you should be able to define any class/object to respond to a message any way you like. Which works fine as long as you are the only developer of code within that language system [start sharing and collaborating with others who have different views of how things should work and you begin to have "standards" problems]. Binary selectors in a mathematical context are an important area that I (and others) discussed during the ANSI x3j20 process. Specifically that of: Reflexive - a op a is true. Symmetric - a op b is true if and only if b op a is true. Transitive - if a op b is true and b op c is true, then a op c is true I suspect you'll find that for many classes which define various compare-op messages, the class authors [in designing #= messages] have not thought about those messages in a mathematical sense or considered hashing issues. Whenever you define/refine a "comparison" message, you must also define/refine its corresponding "hashing" methods. I.e., Comparison issues are directly related to the definition of hash-op values [which during the ANSI process era, many implementations had problems with]. SmallScript (and its ancestor, QKS Smalltalk) define: hash/compare op correspondence --- ------------------------------ MOP #basicHash (corresponding to [MOP] #==) [aliased as #identHash] USER #identEquivHash (corresponding to #==~) [not in QKS Smalltalk] USER #hash (corresponding to #= and #==~) USER #equivHash (corresponding to #=~) Hashing is a mapping function that folds/converts two comparable values into an identical representation. Thus, the hashing operation is "weaker" than a comparison operation. If two objects compare as true then their corresponding hash-messages must return an identical (via #==) value. But given two objects which return the same hash-message value, they may not return true for their corresponding comparison-message. if (a compareOp b) then (a hashOp == b hashOp) must be true BUT if (a hashOp == b hashOp) then (a compareOp b) may return true or false Again, for implementation efficiency reasons, hash values should be constrained to a [whole number; >= 0 integer] value. This becomes an issue when creating derivative hashes (those based on combinations of other hash values). Generally derivative hash values should be composed using bit-operations rather than arithmetic operations to avoid overflowing the [whole number; >= 0 integer] set of values. -- Dave S. [www.smallscript.org] > > Dave Harris, Nottingham, UK | "Weave a circle round him thrice, > brangdon@cix.co.uk | And close your eyes with holy dread, > | For he on honey dew hath fed > http://www.bhresearch.co.uk/ | And drunk the milk of Paradise."