home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #27 / NN_1992_27.iso / spool / comp / lang / clos / 1004 < prev    next >
Encoding:
Text File  |  1992-11-18  |  9.2 KB  |  227 lines

  1. Newsgroups: comp.lang.clos
  2. Path: sparky!uunet!ukma!darwin.sura.net!zaphod.mps.ohio-state.edu!cis.ohio-state.edu!lucid.com!jonl%kuwait
  3. From: jonl%kuwait@lucid.com (Jon L White)
  4. Subject: Unsolvable problems with CLASS-PROTOTYPE
  5. Message-ID: <9211181935.AA05677@kuwait.lucid>
  6. Sender: daemon@cis.ohio-state.edu
  7. Organization: The Ohio State University Department of Computer and Information Science
  8. References: <1992Nov2.214651.18857@jpl-devvax.jpl.nasa.gov>
  9. Date: Wed, 18 Nov 1992 19:35:28 GMT
  10. Lines: 215
  11.  
  12. Alas, the following message got lost somewhere in between the sending of it 
  13. and the comp.lang.clos list; my apologies for being so late with it.
  14.  
  15.  
  16. Date: Thu, 5 Nov 92 10:03:07 PST
  17. From: jonl (Jon L White)
  18. To: charest@Aig.Jpl.Nasa.Gov, peterson@sra.COM
  19. In-Reply-To: your msgs of Wed, 4 Nov 1992 18:32:47 GMT  and  Thu, 5 Nov 1992 15:00:32 GMT
  20. Subject: Avoiding CLASS-PROTOTYPE 
  21.  
  22. re: [Len] Lucid 4.0.2 *does* use MAKE-INSTANCE to create the class prototype. 
  23.     . . . 
  24.     [Eric] the MOP should specify that class instance prototypes be created 
  25.     with allocate-instance instead of using make-instance (as Lucid has done).
  26.  
  27. This isn't fully accurate, and doesn't get at the heart of the problem.
  28. Perhaps I can explain. 
  29.  
  30. First, Lucid "resorts" to MAKE-INSTANCE to supply, lazily, a class-protoype.
  31. But it *doesn't* always "use" MAKE-INSTANCE -- at times, it must just call
  32. ALLOCATE-INSTANCE.   I'll try to explain further below.
  33.  
  34. The real difficuly is not with the MOP proposal -- which does admit of 
  35. a de facto standard in the existence of CLOS:CLASS-PROTOTYPE, even though
  36. it doesn't say how or when the prototypical instance is created.  Rather,
  37. the difficulty encountered by Len is that CLOS standard doesn't constrain
  38. the system from a random creation here and there, for just about any class.
  39. Of course, if it did (i.e., if it proscribed non-user allocations), then
  40. the prototype would have to be created eagerly, rather than lazily, at 
  41. class definition time; and this would be a loss since almost all classes
  42. don't actually need prototypes.
  43.  
  44. Now, Lucid's 4.0 release might not set the division between a prototype's
  45. creation by ALLOCATE-INSTANCE and its creation by MAKE-INSTANCE very tightly;
  46. but it does use ALLOCATE-INSTANCE on some ocasions.    The 4.1 release 
  47. (which is allegedly "shipping" right now) uses MAKE-INSTANCE only for 
  48. metaclass prototypes and for generic-function-class prototypes; your vanilla
  49. user class will have to put up with merely a "skeletal" prototype -- i.e. 
  50. one created only by ALLOCATE-INSTANCE.  So while this seems in line with 
  51. your suggestions that prototypes only use ALLOCATE-INSTANCE, this approach 
  52. still has unsolvable problems with it.  Let me explain.
  53.  
  54. Even with these accommodations, prototypes are at best still an ill-advised
  55. but ocasionally useful kludge.  Suppose a class, system-defined or user-
  56. defined, has as part of its protocol a slot that always has a value 
  57. describing some state about the class; then ALLOCATE-INSTANCE will return 
  58. a very ill-formed object that could easily "crash the system."  It is for 
  59. this reason that Lucid's 4.1 release still calls MAKE-INSTANCE for metaclass
  60. prototypes; metaobject programming would be most awkard if class objects
  61. don't obey the MOP'ish protocol.
  62.  
  63. On the other hand, suppose a class, system-defined or user defined, has an
  64. init method that prevents successful initization.  With the user's freedom
  65. to place random init methods here and there one could even mess up the 
  66. above stated goal of using MAKE-INSTANCE on metaclasses.  So not being able
  67. to presume about how random user-defined classes are to be used (maybe some
  68. are intended to be "abstract" classes that forbid *any* instances?) then 
  69. only ALLOCATE-INSTACE can be used in general.
  70.  
  71. Below is a terminal "dribble" showing an example of a successful creation 
  72. of a metaclass prototype in Lucid 4.1, and another example showing an
  73. intervention that prevents initialization so that only ALLOCATE-INSTACE
  74. is used.  As the example continues -- trying to 'describe' the two
  75. prototypes -- you can begin to see how the violation of class protocol
  76. (in the non-initialized prototype) messes up the system.
  77.  
  78. One last comment.  CLIM seems to have forced prototypes into CLOS, and
  79. because of their coding style, it is even necessary to have a prototype
  80. for the class T. Phooo, T is perhaps the most abstract of abstract classes.
  81. So, several implementations with which I am familiar have a singular-point 
  82. in their code to support a hokey prototype for T.  I used to call it the 
  83. "Moon's Magic Mumble", since Dave Moon referred to this pseudo-instance as 
  84. a little bit of magic.
  85.  
  86.  
  87. In the following example, look at the behaviour of the prototypes for the
  88. two metaclasses WINNING-META-CLASS and LOSING-META-CLASS.
  89.  
  90.  
  91.  
  92. ;;; Lucid Common Lisp/unknown
  93. ;;; [Internal] 4.1.0 Beta-0, 1 November 1992
  94. ;;; Copyright (C) 1985, 1986, 1987, 1988, 1989, 1990, 1991, 1992 by Lucid, Inc.
  95. ;;; All Rights Reserved
  96. ;;;
  97. ;;; This software product contains confidential and trade secret information
  98. ;;; belonging to Lucid, Inc.  It may not be copied for any reason other than
  99. ;;; for archival and backup purposes.
  100. ;;;
  101. ;;; Lucid and Lucid Common Lisp are trademarks of Lucid, Inc.  Other brand
  102. ;;; or product names are trademarks or registered trademarks of their
  103. ;;; respective holders.
  104. ;;;
  105. ;;; This is a preliminary version to be used for testing purposes only.
  106.  
  107. ;;; Loading source file "/net/kuwait/u/jonl/lisp-init.lisp"
  108. ;;; Expanding Dynamic Memory
  109. ;;; Loading binary file "/net/jonl/sun4/tools/defautoload.sbin"
  110. ;;; Warning: Redefining Function MX which used to be defined in "/tmp_mnt/net/pods/2-1/mods/tools/macroexpanders.lisp"
  111. ;;; Warning: Redefining Function MX1 which used to be defined in "/tmp_mnt/net/pods/2-1/mods/tools/macroexpanders.lisp"
  112. ;;; Warning: Redefining Function FIND-CALLERS which used to be defined in "/tmp_mnt/net/pods/2-1/mods/tools/find-callers.lisp"
  113. ;;; Warning: Redefining Function LOAD-SHADOWS which used to be defined in "/tmp_mnt/net/pods/2-1/mods/tools/load-shadows.lisp"
  114.  
  115.  
  116. ;;; So here's a random class, with only a "skeletal", uninitialized prototype
  117.  
  118.  
  119. > (defclass foo () ((a :initform 'a)))
  120. #<Standard-Class FOO>
  121. > (clos:class-prototype *)
  122. #<Foo #XBBEA86>
  123. > (describe *)
  124.  
  125. #<Foo #XBBEA86>
  126.     is an instance of the class FOO:
  127.  The following slots have allocation :INSTANCE:
  128.  A    #<Unbound-Slot 61A>
  129.  
  130.  
  131. ;;; Now let's have a winning metaclass, and watch the successful initialization
  132. ;;;  of it's prototype by tapping into the initialzation protocol.  
  133.  
  134. > (defclass winning-meta-class (standard-class) ())
  135. #<Standard-Class WINNING-META-CLASS>
  136. > (defmethod clos-system:validate-superclass ((x winning-meta-class) 
  137.                           (y standard-class))
  138.     t)
  139. #<Standard-Method VALIDATE-SUPERCLASS (WINNING-META-CLASS STANDARD-CLASS)>
  140. > (defmethod initialize-instance :before ((class winning-meta-class) &key)
  141.     (when (eq (class-of class) (find-class 'winning-meta-class)) ;"exact" class
  142.       (format t "Birth of a Prince!")))
  143. #<Init-Method INITIALIZE-INSTANCE :BEFORE (WINNING-META-CLASS)>
  144.  
  145.  
  146. ;;; And  further, let's have a losing metaclass, which has an init method that
  147. ;;;  aborts any attempt at initialization.
  148.  
  149. > (defclass losing-meta-class (standard-class) ())
  150. #<Standard-Class LOSING-META-CLASS>
  151. > (defmethod clos-system:validate-superclass ((x losing-meta-class) 
  152.                           (y standard-class))
  153.     t)
  154. #<Standard-Method VALIDATE-SUPERCLASS (LOSING-META-CLASS STANDARD-CLASS)>
  155. >  (defmethod initialize-instance :before ((class losing-meta-class) &key)
  156.     (when (eq (class-of class) (find-class 'losing-meta-class))     ;"exact" class
  157.       (format t "Shoot ArchDuke Ferdinand!")
  158.       (error "Lose Big!")))
  159. #<Init-Method INITIALIZE-INSTANCE :BEFORE (LOSING-META-CLASS)>
  160.  
  161.  
  162. ;;; There are no prototypes for these weird metaclasses yet;  TMWFI -- JonL
  163.  
  164.  
  165. (setq winner (clos:class-prototype (find-class 'winning-meta-class)))
  166. Birth of a Prince!
  167. #<Winning-Meta-Class (CLOS:CLASS-PROTOTYPE WINNING-META-CLASS)>
  168.  
  169. > (clos:class-prototype (find-class 'winning-meta-class))
  170. #<Winning-Meta-Class (CLOS:CLASS-PROTOTYPE WINNING-META-CLASS)>
  171.  
  172. ;;; What a winner!
  173.  
  174. > (describe *)
  175. Class Object:
  176. Name:                  (CLOS:CLASS-PROTOTYPE WINNING-META-CLASS)
  177. MetaClass:             WINNING-META-CLASS
  178. Class-Precedence-List: ((CLOS:CLASS-PROTOTYPE WINNING-META-CLASS) STANDARD-OBJECT CLOS::STANDARD-SLOTTED-OBJECT T)
  179. Direct-Superclasses:   (STANDARD-OBJECT)
  180. Direct-Subclasses:     
  181.  
  182.  
  183.  
  184. > (setq loser (clos:class-prototype (find-class 'losing-meta-class)))
  185. Shoot ArchDuke Ferdinand!
  186. #<Losing-Meta-Class  #XAD0A9E>
  187.  
  188. ;;; Note that we "keep trying", but losing, to initialize this protype.
  189.  
  190. > (clos:class-prototype (find-class 'losing-meta-class))
  191. Shoot ArchDuke Ferdinand!
  192. #<Losing-Meta-Class  #XAD0A9E>
  193.  
  194. ;;; What a loser!
  195.  
  196. > (describe loser)
  197. >>Error: The slot CLOS::FULLY-DEFINED-P is unbound in the object #<Losing-Meta-Class  #XAD0A9E>
  198.  
  199. (:GENERIC-FUNCTION SLOT-UNBOUND :|dispatch code|):
  200.    Required arg 0 (CLASS): #<Standard-Class LOSING-META-CLASS>
  201.    Required arg 1 (INSTANCE): #<Losing-Meta-Class  #XAD0A9E>
  202.    Required arg 2 (SLOT-NAME): CLOS::FULLY-DEFINED-P
  203.     0: Supply a value to be put into the slot
  204.     1: Supply one value to use for this particular call
  205.     2: Try fetching this slot again
  206. :A  3: Abort to Lisp Top Level
  207.  
  208. -> 
  209.  
  210. ;;; CLOS::FULLY-DEFINED-P  is an implementational part of the CLASS-FINALIZED
  211. ;;;   protocol.
  212.  
  213.  
  214.  
  215.  
  216.  
  217.  
  218. -- JonL --
  219.  
  220.  
  221.  
  222. P.S.: "TMWFI"  =  "Take My Word For It."
  223.  
  224.  
  225.  
  226.