Re: colored point redux (was: Re: What _is_ exciting about generic functions vs. message sending...)

Pascal Costanza <[email protected]> Sat, 24 Feb 2007 22:16:08 +0100
Newsgroups gmane.comp.lang.lightweight
Message-ID <[email protected]>
On 24 Feb 2007, at 21:56, Vadim Nasardinov wrote:

> On Saturday 24 February 2007 11:37, Pascal Costanza wrote:
>> This whole discussion about naming issues has deteriorated. I am
>> sorry about this because I have taken a part in that. Now, I'd like
>> to make an attempt to get this discussion back on track.
>>
>> Here are two or three examples what generic functions buy you:
>>
>> 1) Assume the standard OOP example of points and how to compare
>> points. Here is an implementation in CLOS:
>>
>> (defclass point ()
>>    ((x :initarg :x :reader x)
>>     (y :initarg :y :reader y)))
>>
>> (defclass color-point (point)
>>    ((c :initarg :color :reader color)))
>>
>> (defmethod eqv ((obj1 point) (obj2 point))
>>    (and (eql (x obj1) (x obj2))
>>         (eql (y obj1) (y obj2))))
>>
>> (defmethod eqv ((obj1 color-point) (obj2 color-point))
>>    (and (call-next-method)
>>         (eql (color obj1) (color obj2))))
>>
>> All the implementations in single-dispatch languages I have seen are
>> ugly and amount to simulating multiple dispatch.
>
> Ah, the venerable the "colored point" example.  I know we've been
> through this before:
>
>     http://people.csail.mit.edu/gregs/ll1-discuss-archive-html/ 
> msg03953.html
>     http://people.csail.mit.edu/gregs/ll1-discuss-archive-html/ 
> msg03983.html
>     http://people.csail.mit.edu/gregs/ll1-discuss-archive-html/ 
> msg04068.html
>     http://people.csail.mit.edu/gregs/ll1-discuss-archive-html/ 
> msg04073.html
>
> ... but here's the thing.  I like my EQV relationship to be
>
>  (a) Reflexive (check)
>  (b) Symmetric (check)
>  (c) Transitive (???)
[...]

> No transitivity.
>
> Don't get me wrong.  I do appreciate the fact that broken code can be
> much terser in Lisp than it is in Java.  That _is_ very exciting.

Well, I haven't given you the specification, so how do you know that  
the code was wrong for my purposes? ;)

But thanks for asking:

(defclass point ()
   ((x :initarg :x :reader x)
    (y :initarg :y :reader y)))

(defclass color-point (point)
   ((c :initarg :color :reader color)))

(defgeneric eqv (obj1 obj2)
   (:method-combination and)
   (:method and (obj1 obj2)
    (eql (class-of obj1) (class-of obj2))))

(defmethod eqv and ((obj1 point) (obj2 point))
   (and (eql (x obj1) (x obj2))
        (eql (y obj1) (y obj2))))

(defmethod eqv and ((obj1 color-point) (obj2 color-point))
   (eql (color obj1) (color obj2)))

(defun compare (point-name1 point1 point-name2 point2)
   (format t "eqv(~A ~A): ~A~%" point-name1 point-name2 (eqv point1  
point2)))

CL-USER 1 > (let
                 ((p      (make-instance 'point       :x 1 :y 1))
                  (p-red  (make-instance 'color-point :x 1 :y  
1 :color 'red))
                  (p-blue (make-instance 'color-point :x 1 :y  
1 :color 'blue)))
               (compare "p-red" p-red "p" p)
               (compare "p" p "p-blue" p-blue)
               (compare "p-red" p-red "p-blue" p-blue))
eqv(p-red p): NIL
eqv(p p-blue): NIL
eqv(p-red p-blue): NIL
NIL


Better?


Pascal

-- 
Pascal Costanza, mailto:[email protected], http://p-cos.net
Vrije Universiteit Brussel, Programming Technology Lab
Pleinlaan 2, B-1050 Brussel, Belgium