20110130

All things being equal...

Alright, this has been floating around for some time and it is time to write it up.

Several object-oriented languages (e.g., Java, Ruby, C++, etc.) have ways to define equality and comparison operators or methods. In Java the Object class defines the equals method, which can be specialized in user code and the Comparable<T> interface.

In Common Lisp, while all the machinery is there to provide such facilities, there has been no push to provide them. I think there are two reasons for this. The first one lies in the widespread use of :test keywords and the programming style it encourages, especially when writing libraries. The second in the influential KMP's paper on The Best of Intentions: EQUAL Rights - and Wrongs - in Lisp.

The first reason does not really needs discussing, the second, a bit. In my honest opinion, there are no real reasons not to have a notion of generic equality (and comparisons) on top of the standard :test machinery, provided that some caution is taken.

Having said so, I built methods for the following generic functions.

(defgeneric AEQUALIS (a b &rest keys &key recursive-p &allow-other-keys)
 (:method ((a T) (b T) &rest keys &key recursive-p &allow-other-keys)
    (eq a b))
 )

(defgeneric COMPARE (a b &rest keys &key recursive-p &allow-other-keys)
   ...)

AEQUALIS is Latin for "equal". The generic function COMPARE returns <, >, =, or /=.

I prepared a specification for them (and an implementation) in order to post a CDR. You can find it in the CLEQCMP directory on my Google docs.

Comments welcome.

Enjoy


(cheers)

6 comments:

  1. How would that replace the :TEST keyword? Most methods of AEQUALIS depend in their behaviour on at least one extra parameter besides the objects to be compared, thus to be able to supply those, you'd need to have a :TEST keyword or similar...

    ReplyDelete
  2. Nope. The :TEST keyword is a "style" in CL, cfr. all the functions that take it as a parameter and some of the libraires "out there". Methods on AEQUALIS do not need a :TEST keyword (which is not in the proposal). Of course, nothing prevents you from passing a :TEST keyword on one of *your* AEQUALIS definitions, but that is *your* choice. Needless to say, if you are doing something like that, you are most probably not exploiting CLOS.

    MA

    ReplyDelete
  3. AEQUALIS seems to be a rather bad name, because it's prone to mistyping. (I'd suggest to use EQUALS as well, as it should be familiar to many developers)

    (Btw, there's also EGAL equality, that Rich Hickey promotes: http://home.pipeline.com/~hbaker1/ObjectIdentity.html)

    ReplyDelete
  4. AEQUALIS is perfect Latin, which, to the dismay of my wife (*), should be used instead of English as a basis of any programming language. Like Lingua Romana Perligata :)

    Having said so, I personally don't like EGAL, even if it has been proposed many years ago by Baker. I would settle for EQUIV or ==.

    Cheers
    --
    Marco

    (*) Who is Greek :)

    ReplyDelete
  5. This may sound like a silly reason to change a spec, but isn't combining optional and keyword arguments considered bad style? Certainly SBCL won't shut up about it.

    ReplyDelete
  6. I wasn't aware that mixing &optional and &key arguments was considered "bad style". I was pointed this out and that SBCL raises a style-warning elsewhere as well. While I do see the point about not mixing &optional and &key (I can change the spec; I have no problems about it), I think that SBCL is erring a bit on the fascist side on a number of issues. Package locking being another. Oh well.

    Marco

    ReplyDelete