dsm@ctt.bellcore.com (David S. Miller) (10/25/90)
I'm thinking of using CLOS to implement a project, and I have a few questions about it. I apologize in advance if any of these questions have been asked before, or are inappropriate for this newsgroup. (1) Are there any public domain (ftp'able) versions of CLOS out there? (for a Sun 3)? (2) Is it possible for an object to be an instance of two disjoint classes? (e.g.) Supposing I have classes representing groups of people such as employees, students, and athletes. What if I want to represent an individual student-employee, or student-athlete, without creating a new class? As far as I can tell, it doesn't seem possible for an object to be an instance of more than one class. Yet, it seems inappropriate to have to create a new class every time you want a new instance to inherit attributes from more than one existing class. (3) Is there any mechanism in CLOS for automatically classifying an object into a class based on attribute values? (e.g.) In the previous example, suppose the 'student' class has an "athletic-prowess' slot. If the value of that slot was set to 'high for a particular instance, then I'd want that instance to be classified into the 'athlete' class as well. The best way that I can think of to handle this is to define a method such as: (defmethod (setf athletic-prowess) ((new-value (eql 'high)) ...) ...classify this instance as an athlete... ) Is there a better way to do this? Thanks in advance for any help on these matters. I will post summaries of responses e-mailed to me that are of general interest. David Miller |INTERNET: dsm@ctt.bellcore.com Bellcore - RRC 1H206 |UUCP: ..!bellcore!ctt!dsm 444 Hoes Lane |PHONE: (201) 699-4533 Piscataway, NJ 08854-4182 | -- David S. Miller |INTERNET: dsm@ctt.bellcore.com Bellcore - RRC 1H206 |UUCP: ..!bellcore!ctt!dsm 444 Hoes Lane |PHONE: (201) 699-4533 Piscataway, NJ 08854-4182 |
scott@alice.coyote.trw.com (Scott Simpson) (10/25/90)
In article <28175@bellcore.bellcore.com> dsm@ctt.bellcore.com (David S. Miller) writes: >I'm thinking of using CLOS to implement a project, and I have a few >(1) Are there any public domain (ftp'able) versions of CLOS out there? >(for a Sun 3)? PCL (Portable Common Loops) from arisia.xerox.com. I believe it is very close to standard CLOS. >(2) Is it possible for an object to be an instance of two disjoint classes? Not that I know of. >(e.g.) Supposing I have classes representing groups of people such as >employees, students, and athletes. What if I want to represent an individual >student-employee, or student-athlete, without creating a new class? Why don't you want to create a new class? Assuming that employees, students and athletes are all disjoint, you could have a hierarchy like person | ------------------------------------------------------ / | \ employee student athlete \ | \ / | \ | ----------------------- | \ | | | \ | student-athlete | ---------------- | | \ | | \ | / \ | ----------- student-employee-athlete / >As far as I can tell, it doesn't seem possible for an object to be an >instance of more than one class. Yet, it seems inappropriate to have >to create a new class every time you want a new instance to inherit >attributes from more than one existing class. You can inherit attributes from more than one class by using multiple inheritance. You still have to create a new class to do multiple inheritance though. Why is creating a new class inappropriate? >(3) Is there any mechanism in CLOS for automatically classifying an >object into a class based on attribute values? > >(e.g.) In the previous example, suppose the 'student' class has an >"athletic-prowess' slot. If the value of that slot was set to 'high >for a particular instance, then I'd want that instance to be >classified into the 'athlete' class as well. Why couldn't you write a routine to take a parameter that is the athletic-prowess? You then compute on this parameter and create either a student or athlete object and return it. Athlete would inherit from student and student would contain the athletic-prowess slot. >The best way that I can think of to handle this is to define a method >such as: >(defmethod (setf athletic-prowess) ((new-value (eql 'high)) ...) > ...classify this instance as an athlete... ) The problem is that you want to reclassify an object after creation time. The only way I know of doing this is to create a brand new object in a different class. If you didn't create a brand new object, then anybody pointing to the old object would suddenly be pointing to a new object of a different type! Ada has this problem with dynamically allocated discriminated record types. Consequently, in Ada, you cannot change the discriminant after the record is dynamically allocated. -- Scott Simpson TRW scott@coyote.trw.com
halvers@betelgeuse.crd.ge.com (Pete Halverson) (10/25/90)
In article <2726886C.2C1B@wilbur.coyote.trw.com> Scott Simpson writes: >In article <28175@bellcore.bellcore.com> David S. Miller writes: >>(3) Is there any mechanism in CLOS for automatically classifying an >>object into a class based on attribute values? Not automatically, no. That kind of functionality hasn't yet trickled down from the high-end knowledge representation schemes (e.g. KRL, LOOM) to the more mundane OOP languages. >> >>(e.g.) In [a] previous example, suppose the 'student' class has an >>"athletic-prowess' slot. If the value of that slot was set to 'high >>for a particular instance, then I'd want that instance to be >>classified into the 'athlete' class as well. >>The best way that I can think of to handle this is to define a method >>such as: >>(defmethod (setf athletic-prowess) ((new-value (eql 'high)) ...) >> ...classify this instance as an athlete... ) > >The problem is that you want to reclassify an object after creation >time. The only way I know of doing this is to create a brand new >object in a different class. The standard method CHANGE-CLASS can be used to mutate an instance into a different class, calling the extendable generic function CHANGE-INSTANCE-FOR-DIFFERENT-CLASS The default method removes old slots and values and adds new ones, leaving any common slots alone. There doesn't seem to be any restriction about what classes of instances may be changed into other classes (as long as they're all standard classes), so presumably specializing an object class is no problem. As Scott pointed out, you *do* need to create a combined class that uses both STUDENT and ATHLETE, so your "classification" method might look something like (defmethod (setf athletic-prowess) ((new-value (eql 'high)) (student STUDENT)) (change-class student 'STUDENT-ATHLETE)) However, I suppose it might be possible for this method to define the appropriate combined class *dynamically*, so that it would work for any class with an ATHLETIC-PROWESS accessor. The precise incantations for that relate to the Meta-Object protocol, though, so they're still not fully defined (and therefore not well supported in existing implementations). >If you didn't create a brand new object, then anybody pointing to the old >object would suddenly be pointing to a new object of a different type! Sounds exactly like what David's asking for---the same object identity, so that existing pointers remain valid, but a more restricted object type. >Ada has this problem with dynamically allocated discriminated record types. >Consequently, in Ada, you cannot change the discriminant after the record >is dynamically allocated. As has been pointed out quite recently in this newsgroup, Common Lisp is not Ada (thank heavens), nor is it Eiffel. Anyway, it sounds like David wants a *restriction* on the original type, which, in those languages, wouldn't necessarily break whatever type assumptions and invariants were derived from the original instance type. -- =============================================================================== Pete Halverson INET: halverson@crd.ge.com GE Corporate R&D Center UUCP: uunet!crd.ge.com!halverson Schenectady, NY "Money for nuthin' and your MIPS for free"
john@linus.mitre.org (John D. Burger) (10/26/90)
The reason a new class has to be created when you want to inherit from two or more classes is that CLOS requires you to define the ORDER of the inheritance. Thus if #<Fred> is an instance of both #<Standard-Class ATHLETE> and #<Standard-Class STUDENT>, it's necessary to know the order in which #<Fred> should inherit from these classes. This must be done in CLOS by defining a NEW class, say #<Standard-Class STUDENT-ATHLETE>, whose DIRECT-SUPERCLASSES slot dictates the order of inheritance. scott@alice.coyote.trw.com (Scott Simpson) writes: >The problem is that you want to reclassify an object after creation >time. The only way I know of doing this is to create a brand new >object in a different class. Actually, one can use CHANGE-CLASS to ``coerce'' an instance from its current class to a new one. Thus (SETF FRED (MAKE-INSTANCE 'STUDENT :NAME "Fred")) #<Instance of STUDENT Fred 1ab3467> (CLASS-OF FRED) #<Standard-Class STUDENT> (CHANGE-CLASS FRED 'ATHLETE) #<Instance of ATHLETE Fred 1ab3467> (CLASS-OF FRED) #<Standard-Class ATHLETE> Note that Fred is the exact same object. It's fairly easy to write CLOS code to cons up new mixtures of existing classes when necessary. For instance, posit a function FIND-MIXTURE, which takes any number of classes as arguments, and finds or creates a new class with exactly those supers. Thus (FIND-MIXTURE 'STUDENT 'ATHLETE) would create a new class, perhaps called STUDENT-ATHLETE, assuming no such class already existed. Then one could call CHANGE-CLASS on Fred and this new class, whenever it became apparent that Fred was not just a student. -- John Burger john@mitre.org "You ever think about .signature files? I mean, do we really need them?" - alt.andy.rooney
jeff@aiai.ed.ac.uk (Jeff Dalton) (10/29/90)
In article <124464@linus.mitre.org> john@mitre.org writes: >The reason a new class has to be created when you want to inherit from >two or more classes is that CLOS requires you to define the ORDER of >the inheritance. This is true as a description. CLOS requires that you define a new class; when you define a class, you have to list the superclasses in some order; and this order constrains the total class precedence list for the class being defined. So, CLOS requires you to define a new class, and that means specifying the inheritance (to an extent -- you specify constraints). But there the new-class requirement explains the define-inheritance requirement. We still need an explanation of the new-class requirement itself. So: is there an inheritance-definition requirement that is independent of the requirement that you define a new class? It's not clear that there is. CLOS does not require that you specify a total order for inheritance. Class definitions specify only a partial order; the rest is an artifact of the algorithm used for building the class precedence list. The algorithm is specified so that the total order is always defined. It could have been otherwise: for example, CLOS implementations might have been allowed to choose any total order consistent with the partial one. So presumably the CLOS designers chose to make things more defined rather than less. However, if you could specify more than one class to MAKE-INSTANCE, those classes would be in some order, and that order could be interpreted in the same way as the order in a DEFCLASS. Inheritance would be no less defined than it was before. On the other hand, the class precedence list would then be a property of an instance rather than a class, at least in some cases, which would make CLOS a different kind of object system than it is. It would be necessary to rething many aspect of the design, or at least make sure they still made sense. So you have to define a new class. But you could define a MAKE-MULTI-INSTANCE that constructed a special-purpose class and then made an instance of it, so you can get something fairly close to this part of what you want.