alanr@chopin.media-lab.media.mit.edu (Alan Ruttenberg) (06/18/91)
I have a question concerning creating a method applicable to one of two classes. Suppose I have two classes A and B. These two classes are distinct. They happen to share similar instance variables, but it is not possible to factor this out to a mixin, since I can't redefine A. I want to write a method which is applicable to either. The cleanest way to express it is: (deftype C () '(or A B)) (defmethod common ((instance C)) ...) This doesn't work. (can't find class C) My only two choices seem to be to either replicate the code, or to factor the body of the definition of common into a defun which is called by both. 1- (defmethod common ((instance A)) the code) (defmethod common ((instance B)) the same code) 2- (defmethod common ((instance A)) (the-code instance)) (defmethod common ((instance B)) (the-code instance)) (defun the-code (instance) the code) So the question is... Is there a more elegant way to do this? -alan
barmar@think.com (Barry Margolin) (06/18/91)
In article <ALANR.91Jun17130803@chopin.media-lab.media.mit.edu> alanr@chopin.media-lab.media.mit.edu (Alan Ruttenberg) writes: >(deftype C () '(or A B)) > >(defmethod common ((instance C)) > ...) > >This doesn't work. (can't find class C) > >My only two choices seem to be to either replicate the code, or to factor the >body of the definition of common into a defun which is called by both. If A and B have any ancestors in common you could define the method on a common ancestor, and then use (check-type instance 'C) to catch misuse. But that's also pretty inelegant. I don't think there's a really elegant way to do this. OO programming generally depends on OO design, and it can get clumsy when you don't have the luxury of redesigning pieces. There was another posting today about adding a mixin to an existing class for which the source isn't available; that's the same kind of problem. Compound type specifiers such as OR can't be used as method specializers because they can introduce ambiguities into the class hierarchy. For instance, if you had (deftype OR1 () '(or A B)) (defmethod common ((instance OR1)) ...) (deftype OR2 () '(or B C)) (defmethod common ((instance OR2)) ...) and then did (common (make-instance 'B)), which method should be chosen? Of your two choices, I'd say the second one (factoring the common code into an ordinary function) is better. This is the nice thing about the fact that CLOS doesn't restrict slot access only to methods. -- Barry Margolin, Thinking Machines Corp. barmar@think.com {uunet,harvard}!think!barmar
jonl%kuwait@lucid.com (Jon L White) (06/18/91)
Date: Mon, 17 Jun 91 17:45:54 -0400
From: Mail Delivery Subsystem <Mailer-Daemon@cis.ohio-state.edu>
Subject: Returned mail: Service unavailable
To: <jonl%kuwait@lucid.com>
----- Transcript of session follows -----
>>> DATA
<<< 554 sendall: too many hops (17 max)
554 <comp.lang.clos@cis.ohio-state.edu>... Service unavailable: Bad file number
----- Unsent message follows -----
. . .
Date: Mon, 17 Jun 91 14:06:25 PDT
From: Jon L White <jonl%kuwait@lucid.com>
Message-Id: <9106172106.AA06676@kuwait>
To: alanr@chopin.media-lab.media.mit.edu
Cc: comp.lang.clos@cis.ohio-state.edu
In-Reply-To: Alan Ruttenberg's message of 17 Jun 91 18:08:03 GMT <ALANR.91Jun17130803@chopin.media-lab.media.mit.edu>
Subject: method definition question
re: My only two choices seem to be to either replicate the code, or to factor
the body of the definition of common into a defun which is called by both.
Procedure abstraction is an excellent technique! (the "common defun"
approach -- Object-oriented programming notwithstanding, reports of
the death of the procedural style are premature.)
By the bye, you'd better take another look at the CLOS spec regarding
the integration of types and classes. DEFTYPE neither creates any
new types (it is like a macro for type names) nor does it even make
any classes.
-- JonL --
lgm@cbnewsc.ATT.COM (lawrence.g.mayka) (06/19/91)
In article <1991Jun17.210108.29347@Think.COM> barmar@think.com (Barry Margolin) writes: In article <ALANR.91Jun17130803@chopin.media-lab.media.mit.edu> alanr@chopin.media-lab.media.mit.edu (Alan Ruttenberg) writes: >(deftype C () '(or A B)) > >(defmethod common ((instance C)) > ...) > >This doesn't work. (can't find class C) > >My only two choices seem to be to either replicate the code, or to factor the >body of the definition of common into a defun which is called by both. If A and B have any ancestors in common you could define the method on a common ancestor, and then use (check-type instance 'C) to catch misuse. But that's also pretty inelegant. If A and B are standard classes, they are guaranteed to have STANDARD-OBJECT as a common superclass; the method can be specialized on that. And any vendor that allows for run-time modification of the class hierarchy should be able to optimize slot accesses in such a method just as well as in more specialized methods. In an ordinary function, on the other hand, SLOT-VALUE cannot generally be optimized. Lawrence G. Mayka AT&T Bell Laboratories lgm@iexist.att.com Standard disclaimer.
sboswell@sdcc13.ucsd.edu (....What Is?....) (06/27/91)
In article <LGM.91Jun18195405@cbnewsc.ATT.COM> lgm@cbnewsc.ATT.COM (lawrence.g.mayka) writes: >In article <1991Jun17.210108.29347@Think.COM> barmar@think.com (Barry Margolin) writes: >In article <ALANR.91Jun17130803@chopin.media-lab.media.mit.edu> alanr@chopin.media-lab.media.mit.edu (Alan Ruttenberg) writes: >>(deftype C () '(or A B)) >> >>(defmethod common ((instance C)) >> ...) >> >>This doesn't work. (can't find class C) >> >>My only two choices seem to be to either replicate the code, or to factor the >>body of the definition of common into a defun which is called by both. > >If A and B have any ancestors in common you could define the method on a >common ancestor, and then use (check-type instance 'C) to catch misuse. >But that's also pretty inelegant. I'm having a similar problem. I wrote an AVL tree in Lisp a few months back using a 4-element list as my basic data structure (left, data, height, right). Now I'm trying to convert it to CLOS. I defined the methods with parameter specializers that make them take my avl-tree class, but I need to be able to have "no avl-tree", which I was implementing as "nil". But of course none of the avl-tree methods recognize the null stuff. Is factoring the only way to get my methods to recognize both avl-tree and null as valid instances of avl-tree? I tried (defclass avl-tree (null) blah blah blah) but it didn't help. If there is no really good solution to this, I'll be amazed, since out of the OOP paradigms I've seen so far, CLOS has been the best. Steve Boswell | This opinion is distributed in the hopes that it whatis@ucsd.edu | will be useful, but WITHOUT ANY WARRANTY... whatis@gnu.ai.mit.edu | -- Steve Boswell | This opinion is distributed in the hopes that it whatis@ucsd.edu | will be useful, but WITHOUT ANY WARRANTY... whatis@gnu.ai.mit.edu |