colored point redux (was: Re: What _is_ exciting about generic functions vs. message sending...)
Vadim Nasardinov <[email protected]> Sat, 24 Feb 2007 15:56:26 -0500
| Newsgroups | gmane.comp.lang.lightweight |
|---|---|
| Message-ID | <[email protected]> |
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 (???)
Here's what we've got:
| $ sbcl
| This is SBCL 1.0, an implementation of ANSI Common Lisp.
| More information about SBCL is available at <http://www.sbcl.org/>.
|
| SBCL is free software, provided as is, with absolutely no warranty.
| It is mostly in the public domain; some portions are provided under
| BSD-style licenses. See the CREDITS and COPYING files in the
| distribution for more information.
| * (defclass point ()
| ((x :initarg :x :reader x)
| (y :initarg :y :reader y)))
|
| #<STANDARD-CLASS POINT>
| * (defclass color-point (point)
| ((c :initarg :color :reader color)))
|
| #<STANDARD-CLASS COLOR-POINT>
| * (defmethod eqv ((obj1 point) (obj2 point))
| (and (eql (x obj1) (x obj2))
| (eql (y obj1) (y obj2))))
| STYLE-WARNING: implicitly creating new generic function EQV
|
| #<STANDARD-METHOD EQV (POINT POINT) {100228B6B1}>
| * (defmethod eqv ((obj1 color-point) (obj2 color-point))
| (and (call-next-method)
| (eql (color obj1) (color obj2))))
|
| #<STANDARD-METHOD EQV (COLOR-POINT COLOR-POINT) {10023B4811}>
| * (defun compare (point-name1 point1 point-name2 point2)
| (format t "eqv(~A ~A): ~A~%" point-name1 point-name2 (eqv point1 point2)))
|
| COMPARE
| * (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): T
| eqv(p p-blue): T
| eqv(p-red p-blue): NIL
| NIL
| * (quit)
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.