objects.hlp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531
  1. The OBJECTS Module
  2. Cris Perdue
  3. Alan Snyder
  4. 11/22/82
  5. -----------------------------
  6. INTRODUCTION
  7. ------------
  8. The OBJECTS module provides simple support for object-oriented
  9. programming in PSL. It is based on the "flavors" facility of the
  10. LISP machine, which is the source of its terminology. The LISP
  11. Machine Manual contains a much longer introduction to the idea of
  12. object oriented programming, generic operations, and the flavors
  13. facility in particular. This discussion goes over the basics of
  14. using flavored objects once briefly to give you an idea of what
  15. is involved, then goes into details.
  16. A datatype is known as a flavor (don't ask). The definition of a
  17. flavor can be thought of in two parts: the DEFFLAVOR form
  18. ("flavor definition"), plus a set of DEFMETHOD forms ("method
  19. definitions") for operating on objects of that flavor.
  20. With the objects package the programmer completely controls what
  21. operations are to be done on objects of each flavor, so this is a
  22. true object-oriented programming facility. Also, all operations
  23. on flavored objects are automatically "generic" operations. This
  24. means that any programs you write that USE flavored objects have
  25. an extra degree of built-in generality.
  26. What does it mean to say that operations on flavored objects are
  27. generic? This means that the operations can be done on an object
  28. of any flavor, just so long as the operations are defined for
  29. that flavor of object. The same operation can be defined for
  30. many flavors, and whenever the operation is invoked, what is
  31. actually done will depend on the flavor of the object it is being
  32. done to.
  33. We may wish to write a scanner that reads a sequence of
  34. characters out of some object and processes them. It does not
  35. need to assume that the characters are coming from a file, or
  36. even from an I/O channel.
  37. Suppose the scanner gets a character by invoking the
  38. GET-CHARACTER operation. In this case any object of a flavor
  39. with a GET-CHARACTER operation can be passed to the scanner, and
  40. the GET-CHARACTER operation defined for that object's flavor will
  41. be done to fetch the character. This means that the scanner can
  42. get characters from a string, or from a text editor's buffer, or
  43. from any object at all that provides a GET-CHARACTER operation.
  44. The scanner is automatically general.
  45. DEFFLAVOR
  46. A flavor definition looks like:
  47. (defflavor flavor-name (var1 var2 ...) () option1 option2 ...)
  48. Example:
  49. (defflavor complex-number
  50. (real-part
  51. (imaginary-part 0.0))
  52. ()
  53. gettable-instance-variables
  54. initable-instance-variables
  55. )
  56. A flavor definition specifies the fields, components, or in our
  57. terminology, the "instance variables" that each object of that
  58. flavor is to have. The mention of the instance variable
  59. imaginary-part indicated that by default the imaginary part of a
  60. complex number will be initialized to 0.0. There is no default
  61. initialization for the real-part.
  62. Instance variables may be strictly part of the implementation of
  63. a flavor, totally invisible to users. Typically though, some of
  64. the instance variables are directly visible in some way to the
  65. user of the object. The flavor definition may specify
  66. "initable-instance-variables", "gettable-instance-variables", and
  67. "settable-instance-variables". None, some of, or all of the
  68. instance variables may be specified in each option.
  69. CREATING OBJECTS
  70. The function MAKE-INSTANCE provides a convenient way to create
  71. objects of any flavor. The flavor of the object to be created
  72. and the initializations to be done are given as parameters in a
  73. way that is fully independent of the internal representation of
  74. the object.
  75. METHODS
  76. The function "=>", whose name is intended to suggest the sending
  77. of a message to an object, is usually used to invoke a method.
  78. Examples:
  79. (=> my-object zap)
  80. (=> thing1 set-location 2.0 3.4)
  81. The first "argument" to => is the object being operated on:
  82. my-object and thing1 in the examples. The second "argument" is
  83. the name of the method to be invoked: zap and set-location. The
  84. method name IS NOT EVALUATED. Any further arguments become
  85. arguments to the method. (There is a function SEND which is just
  86. like => except that the method name argument is evaluated just
  87. like everything else.)
  88. Once an object is created, all operations on it are performed by
  89. "methods" defined for objects of its flavor. The flavor
  90. definition itself also defines some methods. For each "gettable"
  91. instance variable, a method of the same name is defined which
  92. returns the current value of that instance variable. For
  93. "settable" instance variables a method named "set-<variable
  94. name>" is defined. Given a new value for the instance variable,
  95. the method sets the instance variable to have that value.
  96. SANCTITY OF OBJECTS
  97. Most LISPs and PSL in particular leave open the possibility for
  98. the user to perform illicit operations on LISP objects. Objects
  99. defined by the objects package are represented as ordinary LISP
  100. objects (vectors at present), so in a sense it is quite easy to
  101. do illicit operations on them: just operate directly on its
  102. representation (do vector operations).
  103. On the other hand, there are major practical pitfalls in doing
  104. this. The representation of a flavor of objects is generated
  105. automatically, and there is no guarantee that a particular flavor
  106. definition will result in a particular representation of the
  107. objects. There is also no guarantee that the representation of a
  108. flavor will remain the same over time. It is likely that at some
  109. point vectors will no longer even be used as the representation.
  110. In addition, using the objects package is quite convenient, so
  111. the temptation to operate on the underlying representation is
  112. reduced. For debugging, one can even define a couple of extra
  113. methods "on the fly" if need be.
  114. REFERENCE INFORMATION
  115. ---------------------
  116. LOADING THE MODULE
  117. NOTE: THIS FILE DEFINES BOTH MACROS AND ORDINARY LISP FUNCTIONS.
  118. IT MUST BE LOADED BEFORE ANY OF THESE FUNCTIONS ARE USED. The
  119. recommended way of doing this is to put the expression:
  120. (BothTimes (load objects)) at the beginning of your source file.
  121. This will cause the package to be loaded at both compile and load
  122. time.
  123. DEFFLAVOR - Define a new flavor of Object
  124. The form is:
  125. (defflavor <name> <instance-variables> <mixin-flavors> <options>)
  126. Examples:
  127. (defflavor complex-number (real-part imaginary-part) ()
  128. gettable-instance-variables
  129. initable-instance-variables
  130. )
  131. (defflavor complex-number ((real-part 0.0)
  132. (imaginary-part 0.0)
  133. )
  134. ()
  135. gettable-instance-variables
  136. (settable-instance-variables real-part)
  137. )
  138. The <instance-variables> form a list. Each member of the list is
  139. either a symbol (id) or a list of 2 elements. The 2-element list
  140. form consists of a symbol and a default initialization form.
  141. Note: Do not use names like "IF" or "WHILE" for instance
  142. variables: they are translated freely within method bodies (see
  143. DEFMETHOD). The translation process is not very smart about
  144. which occurrences of the symbol for an instance variable are
  145. actually uses of the variable, though it does understand the
  146. nature of QUOTE.
  147. The <mixin-flavors> list must be empty. In the LISP machine
  148. flavors facility, this may be a list of names of other flavors.
  149. Recognized options are:
  150. (GETTABLE-INSTANCE-VARIABLES var1 var2 ...)
  151. (SETTABLE-INSTANCE-VARIABLES var1 var2 ...)
  152. (INITABLE-INSTANCE-VARIABLES var1 var2 ...)
  153. GETTABLE-INSTANCE-VARIABLES [make all instance variables GETTABLE]
  154. SETTABLE-INSTANCE-VARIABLES [make all instance variables SETTABLE]
  155. INITABLE-INSTANCE-VARIABLES [make all instance variables INITABLE]
  156. An empty list of variables is taken as meaning all variables
  157. rather than none, so (GETTABLE-INSTANCE-VARIABLES) is equivalent
  158. to GETTABLE-INSTANCE-VARIABLES.
  159. For each gettable instance variable a method of the same name is
  160. generated to access the instance variable. If instance variable
  161. LOCATION is gettable, one can invoke (=> <object> LOCATION).
  162. For each settable instance variable a method with the name
  163. SET-<name> is generated. If instance variable LOCATION is
  164. settable, one can invoke (=> <object> SET-LOCATION <expression>).
  165. Settable instance variables are always also gettable and initable
  166. by implication. If this feature is not desired, define a method
  167. such as SET-LOCATION directly rather than declaring the instance
  168. variable to be settable.
  169. Initable instance variables may be initialized via options to
  170. MAKE-INSTANCE or INSTANTIATE-FLAVOR. See below.
  171. DEFMETHOD - Define a method on an existing flavor.
  172. The form is:
  173. (defmethod (<flavor-name> <method-name>) (<arg> <arg> . . . )
  174. <expression>
  175. <expression>
  176. . . .
  177. )
  178. The <flavor-name>, the <method-name>, and each <arg> are all
  179. identifiers. There may be zero or more <arg>s.
  180. Examples:
  181. (defmethod (complex-number real-part) ()
  182. real-part)
  183. (defmethod (complex-number set-real-part) (new-real-part)
  184. (setf real-part new-real-part))
  185. The body of a method can refer to any instance variable of the
  186. flavor by using the name just like an ordinary variable. They
  187. can set them using SETF. All occurrences of instance variables
  188. (except within vectors or quoted lists) are translated to an
  189. invocation of the form (IGETV SELF n).
  190. The body of a method can also freely use SELF much as though it
  191. were another instance variable. SELF is bound to the object that
  192. the method applies to. SELF may not be setq'ed or setf'ed.
  193. Example using SELF:
  194. (defmethod (toaster plug-into) (socket)
  195. (setf plugged-into socket)
  196. (=> socket assert-as-plugged-in self))
  197. MAKE-INSTANCE - Create a new instance of a flavor.
  198. Examples:
  199. (make-instance 'complex-number)
  200. (make-instance 'complex-number 'real-part 0.0 'imaginary-part 1.0)
  201. MAKE-INSTANCE takes as arguments a flavor name and an optional
  202. sequence of initializations, consisting of alternating pairs of
  203. instance variable names and corresponding initial values. Note
  204. that all the arguments are evaluated.
  205. Initialization of a newly made object happens as follows:
  206. Each instance variable with initialization specified in the call
  207. to make-instance is initialized to the value given. Any instance
  208. variables not initialized in this way, but having default
  209. initializations specified in the flavor definition are
  210. initialized by the default initialization specified there. All
  211. other instance variables are initialized to the symbol *UNBOUND*.
  212. If a method named INIT is defined for this flavor of object, that
  213. method is invoked automatically after the initializations just
  214. discussed. The INIT method is passed as its one argument a list
  215. of alternating variable names and initial values. This list is
  216. the result of evaluating the initializations given to
  217. MAKE-INSTANCE. For example, if we call:
  218. (make-instance 'complex-number 'real-part (sin 30)
  219. 'imaginary-part (cos 30))
  220. then the argument to the INIT method (if any) would be
  221. (real-part .5 imaginary-part .866).
  222. The INIT method may do anything desired to set up the desired
  223. initial state of the object.
  224. At present, this value passed to the INIT method is of virtually
  225. no use to the INIT method since the values have been stored into
  226. the instance variables already. In the future, though, the
  227. objects package may be extended to permit keywords other than
  228. names of instance variables to be in the initialization part of
  229. calls to make-instance. If this is done, INIT methods will be
  230. able to use the information by scanning the argument.
  231. INSTANTIATE-FLAVOR
  232. This is the same as MAKE-INSTANCE, except that the initialization
  233. list is provided as a single (required) argument.
  234. Example:
  235. (instantiate-flavor 'complex-number
  236. (list 'real-part (sin 30) 'imaginary-part (cos 30)))
  237. OPERATING ON OBJECTS
  238. --------------------
  239. Operations on an object are done by the methods of the flavor of
  240. the object. We say that a method is invoked, or we may say that
  241. a message is sent to the object. The notation suggests the
  242. sending of messages. In this metaphor, the name of the method to
  243. use is part of the message sent to the object, and the arguments
  244. of the method are the rest of the message. There are several
  245. approaches to invoking a method:
  246. => - Convenient form for sending a message
  247. Examples:
  248. (=> r real-part)
  249. (=> r set-real-part 1.0)
  250. The message name is not quoted. Arguments to the method are
  251. supplied as arguments to =>. In these examples, r is the object,
  252. real-part and set-real-part are the methods, and 1.0 is the
  253. argument to the set-real-part method.
  254. SEND - Send a Message (Evaluated Message Name)
  255. Examples:
  256. (send r 'real-part)
  257. (send r 'set-real-part 1.0)
  258. The meanings of these two examples are the same as the meanings
  259. of the previous two. Only the syntax is different: the message
  260. name is quoted.
  261. FANCY FORMS OF SEND
  262. SEND-IF-HANDLES - Conditionally Send a Message (Evaluated Message Name)
  263. Examples:
  264. (send-if-handles r 'real-part)
  265. (send-if-handles r 'set-real-part 1.0)
  266. SEND-IF-HANDLES is like SEND, except that if the object defines no method
  267. to handle the message, no error is reported and NIL is returned.
  268. LEXPR-SEND - Send a Message (Explicit "Rest" Argument List)
  269. Examples:
  270. (lexpr-send foo 'bar a b c list)
  271. The last argument to LEXPR-SEND is a list of the remaining arguments.
  272. LEXPR-SEND-IF-HANDLES
  273. This is the same as LEXPR-SEND, except that no error is reported
  274. if the object fails to handle the message.
  275. LEXPR-SEND-1 - Send a Message (Explicit Argument List)
  276. Examples:
  277. (lexpr-send-1 r 'real-part nil)
  278. (lexpr-send-1 r 'set-real-part (list 1.0))
  279. Note that the message name is quoted and that the argument list
  280. is passed as a single argument to LEXPR-SEND-1.
  281. LEXPR-SEND-1-IF-HANDLES
  282. This is the same as LEXPR-SEND-1, except that no error is reported
  283. if the object fails to handle the message.
  284. USEFUL FUNCTION(s) ON OBJECTS
  285. -----------------------------
  286. OBJECT-TYPE
  287. The OBJECT-TYPE function returns the type (an ID) of the
  288. specified object, or NIL, if the argument is not an object. At
  289. present this function cannot be guaranteed to distinguish between
  290. objects created by the OBJECTS package and other LISP entities,
  291. but the only possible confusion is with vectors.
  292. DEBUGGING INFORMATION
  293. ---------------------
  294. Any object may be displayed symbolically by invoking the method
  295. DESCRIBE, e.g. (=> x describe). This method prints the name of
  296. each instance variable and its value, using the ordinary LISP
  297. printing routines. Flavored objects are liable to be complex and
  298. nested deeply or even circular. This makes it often a good idea
  299. to set PRINLEVEL to a small integer before printing structures
  300. containing objects to control the amount of output.
  301. When printed by the standard LISP printing routines, "flavored
  302. objects" appear as vectors whose zeroth element is the name of
  303. the flavor.
  304. For each method defined, there is a corresponding LISP function
  305. named <flavor-name>$<method-name>. Such function names show up
  306. in backtrace printouts.
  307. It is permissible to define new methods on the fly for debugging
  308. purposes.
  309. DECLARE and UNDECLARE
  310. ---------------------
  311. *** Read these warnings carefully! ***
  312. This facility can reduce the overhead of invoking methods on
  313. particular variables, but it should be used sparingly. It is not
  314. well integrated with the rest of the language. At some point a
  315. proper declaration facility is expected and then it will be
  316. possible to make declarations about objects, integers, vectors,
  317. etc., all in a uniform and clean way.
  318. The DECLARE macro allows you to declare that a specific symbol is
  319. bound to an object of a specific flavor. This allows the flavors
  320. implementation to eliminate the run-time method lookup normally
  321. associated with sending a message to that variable, which can
  322. result in an appreciable improvement in execution speed. This
  323. feature is motivated solely by efficiency considerations and
  324. should be used ONLY where the performance improvement is
  325. critical.
  326. Details: if you declare the variable X to be bound to an object
  327. of flavor FOO, then WITHIN THE CONTEXT OF THE DECLARATION (see
  328. below), expressions of the form (=> X GORP ...) or (SEND X 'GORP
  329. ...) will be replaced by function invocations of the form
  330. (FOO$GORP X ...). Note that there is no check made that the
  331. flavor FOO actually contains a method GORP. If it does not, then
  332. a run-time error "Invocation of undefined function FOO$GORP" will
  333. be reported.
  334. WARNING: The DECLARE feature is not presently well integrated
  335. with the compiler. Currently, the DECLARE macro may be used only
  336. as a top-level form, like the PSL FLUID declaration. It takes
  337. effect for all code evaluated or compiled henceforth. Thus, if
  338. you should later compile a different file in the same compiler,
  339. the declaration will still be in effect! THIS IS A DANGEROUS
  340. CROCK, SO BE CAREFUL! To avoid problems, I recommend that
  341. DECLARE be used only for uniquely-named variables. The effect of
  342. a DECLARE can be undone by an UNDECLARE, which also may be used
  343. only as a top-level form. Therefore, it is good practice to
  344. bracket your code in the source file with a DECLARE and a
  345. corresponding UNDECLARE.
  346. Here are the syntactic details:
  347. (DECLARE FLAVOR-NAME VAR1 VAR2 ...)
  348. (UNDECLARE VAR1 VAR2 ...)
  349. *** Did you read the above warnings??? ***
  350. REPRESENTATION INFORMATION
  351. --------------------------
  352. (You don't need to know any of this to use this stuff.)
  353. A flavor-name is an ID. It has the following properties:
  354. VARIABLE-NAMES A list of the instance variables of the flavor, in
  355. order of their location in the instance vector.
  356. This property exists at compile time, dskin time, and
  357. load time.
  358. INITABLE-VARIABLES A list of the instance variables that have been
  359. declared to be INITABLE. This property exists at
  360. dskin time and at load time.
  361. METHOD-TABLE An association list mapping each method name (ID)
  362. defined for the flavor to the corresponding function
  363. name (ID) that implements the method. This property
  364. exists at dskin time and at load time.
  365. INSTANCE-VECTOR-SIZE An integer that specifies the number of elements
  366. in the vector that represents an instance of this
  367. flavor. This property exists at dskin time and at
  368. load time. It is used by MAKE-INSTANCE.
  369. The function that implements a method has a name of the form
  370. FLAVOR$METHOD. Each such function ID has the following properties:
  371. SOURCE-CODE A list of the form (LAMBDA (SELF ...) ...) which is
  372. the untransformed source code for the method.
  373. This property exists at compile time and dskin time.
  374. Implementation Note:
  375. A tricky aspect of the code that implements the objects package
  376. is making sure that the right things happen at the right time.
  377. When a source file is read and evaluated (using DSKIN), then
  378. everything must happen at once. However, when a source file is
  379. compiled to produce a FASL file, then some actions must be
  380. performed at compile-time, whereas other actions are supposed to
  381. occur when the FASL file is loaded. Actions to occur at compile
  382. time are performed by macros; actions to occur at load time are
  383. performed by the forms returned by macros.
  384. Another goal of the implementation is to avoid consing whenever
  385. possible during method invocation. The current scheme prefers to
  386. compile into (APPLY HANDLER (LIST args...)), for which the PSL
  387. compiler will produce code that performs no consing.