home *** CD-ROM | disk | FTP | other *** search
/ ftp.pasteur.org/FAQ/ / ftp-pasteur-org-FAQ.zip / FAQ / lisp-faq / part5 < prev    next >
Encoding:
Internet Message Format  |  1997-08-14  |  28.6 KB

  1. Path: senator-bedfellow.mit.edu!bloom-beacon.mit.edu!news-out.internetmci.com!infeed1.internetmci.com!newsfeed.internetmci.com!news-peer.sprintlink.net!news.sprintlink.net!Sprint!news.maxwell.syr.edu!news.cis.ohio-state.edu!nntp.sei.cmu.edu!fs7.ece.cmu.edu!cantaloupe.srv.cs.cmu.edu!mkant
  2. From: mkant+@cs.cmu.edu (Mark Kantrowitz)
  3. Newsgroups: comp.lang.lisp,comp.lang.clos,news.answers,comp.answers
  4. Subject: FAQ: Object-oriented Programming in Lisp 5/7 [Monthly posting]
  5. Supersedes: <LISP_5_868777228@CS.CMU.EDU>
  6. Followup-To: poster
  7. Date: 13 Aug 1997 07:11:03 GMT
  8. Organization: Carnegie-Mellon University, School of Computer Science
  9. Lines: 589
  10. Approved: news-answers-request@MIT.Edu
  11. Distribution: world
  12. Expires: 24 Sep 1997 07:00:20 GMT
  13. Message-ID: <LISP_5_871455620@CS.CMU.EDU>
  14. References: <LISP_4_871455620@CS.CMU.EDU>
  15. Reply-To: ai+lisp-faq@cs.cmu.edu
  16. NNTP-Posting-Host: glinda.oz.cs.cmu.edu
  17. Summary: Questions about CLOS, PCL and object-oriented programming in Lisp
  18. Xref: senator-bedfellow.mit.edu comp.lang.lisp:28930 comp.lang.clos:4325 news.answers:109687 comp.answers:27565
  19.  
  20. Archive-name: lisp-faq/part5
  21. Last-Modified: Thu Feb 13 09:10:34 1997 by Mark Kantrowitz
  22. Version: 1.56
  23. Maintainer: Mark Kantrowitz and Barry Margolin <ai+lisp-faq@cs.cmu.edu>
  24. URL: http://www.cs.cmu.edu/Web/Groups/AI/html/faqs/lang/lisp/top.html
  25. Size: 28488 bytes, 597 lines
  26.  
  27. ;;; ****************************************************************
  28. ;;; Answers to Frequently Asked Questions about Lisp ***************
  29. ;;; ****************************************************************
  30. ;;; Written by Mark Kantrowitz and Barry Margolin
  31. ;;; lisp_5.faq
  32.  
  33. This post contains Part 5 of the Lisp FAQ. It is cross-posted to the
  34. newsgroup comp.lang.clos because it contains material of interest to
  35. people concerned with CLOS, PCL and object-oriented programming in
  36. Lisp. The other parts of the Lisp FAQ are posted only to the
  37. newsgroups comp.lang.lisp and news.answers.
  38.  
  39. If you think of questions that are appropriate for this FAQ, or would
  40. like to improve an answer, please send email to us at ai+lisp-faq@cs.cmu.edu.
  41.  
  42. CLOS/PCL Questions (Part 5):
  43.  
  44.   [5-0]   What is CLOS (PCL) and where can I get it?
  45.           How do you pronounce CLOS? What is the Meta-Object Protocol (MOP)?
  46.   [5-1]   What documentation is available about object-oriented
  47.           programming in Lisp?  
  48.   [5-2]   How do I write a function that can access defstruct slots by
  49.           name?  I would like to write something like 
  50.           (STRUCTURE-SLOT <object> '<slot-name>).   
  51.   [5-3]   How can I list all the CLOS instances in a class?
  52.   [5-4]   How can I store data and CLOS instances (with possibly circular
  53.           references) on disk so that they may be retrieved at some later
  54.           time? (Persistent Object Storage)
  55.   [5-5]   Given the name of a class, how can I get the names of its slots?
  56.   [5-6]   Free CLOS software.
  57.   [5-7]   Common CLOS Blunders
  58.  
  59. Search for \[#\] to get to question number # quickly.
  60.  
  61. In general, questions about object oriented programming in Lisp,
  62. especially questions about using CLOS or compiling PCL, should be
  63. directed to the newsgroup comp.lang.clos.
  64.  
  65. The comp.lang.clos newsgroup is archived in
  66.    ftp.cs.cmu.edu:/user/ai/pubs/news/comp.lang.clos/
  67. on a weekly basis.
  68.  
  69. ----------------------------------------------------------------
  70. Subject: [5-0]  What is CLOS (PCL) and where can I get it?
  71.                 How do you pronounce CLOS?
  72.  
  73. CLOS (Common Lisp Object System) is the object-oriented programming
  74. standard for Common Lisp. It is the successor to Symbolics FLAVORS and
  75. Xerox LOOPS (Lisp Object Oriented Programming System). The acronym
  76. CLOS is pronouned either as "See-Loss" or "Closs" ("Claws"), depending
  77. on taste. PCL (Portable Common Loops) is a portable CLOS
  78. implementation, and is available by anonymous ftp from 
  79.    parcftp.xerox.com:/pub/pcl/ [13.1.64.94]
  80. Also in the same directory are sources for CLX R5 and an inspecter.
  81.  
  82. Most Common Lisp implementations now include their own CLOS
  83. implementations. Common Lisp implementations with native CLOS include:
  84. MCL, {A}KCL, Allegro CL (including Allegro CL\PC), Ibuki, Lucid,
  85. Medley, Symbolics Genera, CLOE, and Harlequin LispWorks. CMU CL uses a
  86. customized version of PCL as their CLOS. However, not all native CLOS
  87. implementations have as detailed a meta-object protocol as PCL. For
  88. example, MCL 2.0 users sometimes use the july-1d version of PCL
  89. instead of the native CLOS for precisely this reason.
  90.  
  91. The book ``The Art of the Metaobject Protocol'' (see below) includes
  92. the CLOS Metaobject Protocol specification as chapters 5 and 6.  The
  93. sources for the MOP spec itself are available from 
  94.    parcftp.xerox.com:/pub/pcl/mop/ [13.1.64.94]
  95. as the file spec.tar.Z, but this is no substitute for buying the
  96. book, since the book contains a lot of useful explanatory material
  97. beyond the spec. The Closette files related to the book are also
  98. available from parcftp as the file closette.lisp.
  99.  
  100. The CLOS code repository is available by anonymous ftp to
  101.    nervous.cis.ohio-state.edu:/pub/lispusers/clos/ [128.146.61.200] 
  102. If you've got code you'd like to add to the repository, send mail to
  103. Arun Welch, commonloops-request@cis.ohio-state.edu. 
  104.  
  105. ----------------------------------------------------------------
  106. Subject: [5-1] What documentation is available about object-oriented
  107.                programming in Lisp? 
  108.  
  109. Books about object-oriented programming in Lisp include:
  110.  
  111.    1. dpANS CL describes the entire Common Lisp language, which includes the
  112.       CLOS standard.  Informally, CLtL2 can also be used to learn about CLOS, 
  113.       but please remember that CLtL2 is not an official X3J13 committee
  114.       document. (The presentation of CLtL2 differs from that of the draft
  115.       proposed standard, and some matters of fact have changed in the proposed
  116.       standard since the publication of CLtL2.)
  117.  
  118.    2. Sonya E. Keene
  119.       "Object-Oriented Programming in Common Lisp: 
  120.        A Programmer's Guide to CLOS"
  121.       Addison-Wesley (Reading, MA), 1989. 266 pages. ISBN 0-201-17589-4.
  122.            Tutorial introduction to CLOS with many examples and
  123.            a lot of good advice for designing large programs using CLOS.
  124.  
  125.    3. Jo A. Lawless and Molly M. Miller.
  126.       "Understanding CLOS: the Common Lisp Object System"
  127.       Digital Press, 1991. 192 pages.
  128.  
  129.    4. Gregor Kiczales, Jim des Rivieres, and Daniel G. Bobrow.
  130.       "The Art of the Metaobject Protocol"
  131.       MIT Press, 1991. 335 pages. ISBN 0-262-61074-4, $34.95.
  132.            The first part of the book presents a model CLOS implementation,
  133.            introduces the basic principles of metaobject protocols, and 
  134.            works through the key elements of the CLOS Metaobject Protocol.
  135.            The second half is the detailed specification of the CLOS
  136.            Metaobject Protocol. A simple working interpreter suitable
  137.            for experimentation is contained in an appendix.
  138.  
  139.    5. Robert R. Kessler and Amy R. Petajan.
  140.       "LISP, Objects, and Symbolic Programming"
  141.       Scott, Foresman and Company (Glenview, IL), 1988. 644 pages.
  142.            Includes a small Lisp compiler.
  143.  
  144.    6. A short introduction to CLOS written by Jeff Dalton of the
  145.       University of Edinburgh <J.Dalton@ed.ac.uk> is available by
  146.       anonymous ftp from  
  147.          ftp.aiai.ed.ac.uk:/pub/packages/lisp/random/ 
  148.       as the file clos-guide.
  149.  
  150.    7. Andreas Paepcke, editor.
  151.       "Object-Oriented Programming: The CLOS Perspective"
  152.       MIT Press, 1993. 400 pages, ISBN 0-262-16136-2 ($40).
  153.          This book is a collection of essays on the following topics:
  154.            -  Description of CLOS and its design philosophy.
  155.            -  The Metaobject Protocol and its use.
  156.            -  Comparison of CLOS with Smalltalk, Eiffel, Sather, and C++.
  157.            -  CLOS Uses and Methodology. Descriptions of two large CLOS
  158.               applications (Sun's LispView and a hybrid knowledge
  159.               representation tool) and an approach to documenting
  160.               object-oriented protocols (similar to that of AMOP).
  161.            -  Implementation details. Descriptions of TI CLOS for the
  162.               Explorer and PCL's method dispatch mechanism.
  163.  
  164. ----------------------------------------------------------------
  165. Subject: [5-2] How can I write a function that can access defstruct slots 
  166.                by name?  I would like to write something like 
  167.                (STRUCTURE-SLOT <object> '<slot-name>).
  168.  
  169. There is currently no portable, built-in way to access structure slots
  170. given only the name.  If your Common Lisp includes an implementation
  171. of CLOS that supports the meta-object protocol specified in the
  172. original X3J13 draft spec (document X3J13/88-003), then it probably will
  173. allow (SLOT-VALUE <object> '<slot-name>); however, not all
  174. implementations of CLOS currently provide this.  Lacking this, some
  175. implementations may provide implementation-dependent functions that
  176. allow access to structure slots by name; note that this may cause
  177. saved images to be larger, as some implementations normally open-code
  178. structure accessors and discard slot name information.
  179.  
  180. While it is not possible to write a fully general STRUCTURE-SLOT function,
  181. it is not very difficult to write version that handles specific structure
  182. types.  For instance, after defining:
  183.  
  184.    (defstruct spaceship name captain position velocity)
  185.  
  186. one may then define:
  187.  
  188.    (defun spaceship-slot (spaceship slot-name)
  189.      (ecase slot-name
  190.        (name (spaceship-name spaceship))
  191.        (captain (spaceship-captain spaceship))
  192.        (position (spaceship-position spaceship))
  193.        (velocity (spaceship-velocity spaceship))))
  194.  
  195. or using CLOS (generic functions):
  196.  
  197. (defgeneric spaceship-slot (spaceship slot-name)
  198.   (:method ((x spaceship) (slot (eql :name)))
  199.     (spaceship-name x))
  200.   (:method ((x spaceship) (slot (eql :captain)))
  201.     (spaceship-captain x))
  202.   (:method ((x spaceship) (slot (eql :position)))
  203.     (spaceship-position x))
  204.   (:method ((x spaceship) (slot (eql :velocity)))
  205.     (spaceship-velocity x)))
  206.  
  207. Another popular way to define this is:
  208.  
  209.    (defun spaceship-slot (spaceship slot-name)
  210.      (funcall (symbol-function
  211.                 (find-symbol (format nil "SPACESHIP-~A" slot-name)
  212.                              #.(package-name *package*)))
  213.               spaceship))
  214.  
  215. I personally recommend the first version.  It is likely to be much faster
  216. and more memory efficient than the second version.  It's also easy to get
  217. the second one wrong; many people forget to specify the package argument to
  218. FIND-SYMBOL, which can cause incorrect results when the package at run time
  219. is different from the one at compile time.  Even my version assumes that
  220. SPACESHIP-SLOT is being defined in a file that is in the same package as
  221. the one containing the structure definition; if this isn't the case,
  222. #.(PACKAGE-NAME *PACKAGE*) should be replaced by a string naming the
  223. correct package.
  224.  
  225. Another workaround is to define a MY-DEFSTRUCT macro that parses the
  226. defstruct arguments and expands into a call to DEFSTRUCT along with a
  227. definition of the runtime slot-accessor function.
  228.  
  229. Some non-portable techniques include the use of SYSTEM:STRUCTURE-REF
  230. in Lucid (LCL:STRUCTURE-REF in earlier versions of Lucid) and 
  231. EXCL:STRUCTURE-REF in Allegro. 
  232. ----------------------------------------------------------------
  233. Subject: [5-3] How can I list all the CLOS instances in a class?
  234.  
  235. There is no built-in way to enumerate the instances of a class.  If you are
  236. only interested in listing the instances of classes that you have defined,
  237. it is not very difficult to implement it as part of your class definition.
  238. Add a shared slot, e.g. ALL-INSTANCES, with an initial value of NIL, to the
  239. class definition.  Then write an after-method on INITIALIZE-INSTANCE for
  240. this class, which pushes the instance being initialized onto ALL-INSTANCES.
  241. Note that this must be done separately for each class that wants to maintain
  242. such a list; it can't be encapsulated in a mixin class, because all its
  243. dependent classes would share the same ALL-INSTANCES slot.  A compromise
  244. would be to use a mixin to define the INITIALIZE-INSTANCE after-method (and
  245. any other general-purpose methods that use the slot), but not the shared
  246. slot; it would be up to the descendant classes to define the slot at the
  247. level of the class hierarchy that is appropriate. You could also try
  248. defining the classes that need instance-recording as instances of a
  249. metaclass that holds the instance registry on the class object. The
  250. recording behavior could then be built-in to an after method on
  251. initialize-instance for the root class of the metaclass, or even
  252. allocate-instance. To allow for garbage collection of old instances,
  253. you will also need to define a generic function to remove the recorded
  254. instances from the list of instances.
  255. ----------------------------------------------------------------
  256. Subject: [5-4]  How can I store data and CLOS instances (with possibly 
  257.                 circular references) on disk so that they may be
  258.                 retrieved at some later time? (Persistent Object Storage)
  259.  
  260. There are two approaches to CLOS object persistence. The first uses
  261. regular CLOS facilities in concert with a standard file system. The
  262. second uses a more sophisticated storage facility, such as a database.
  263. The first solution provides just the persistence, and usually cannot
  264. retrieve only some of the objects from disc. The second goes beyond this
  265. by providing some or all of the facilities typically associated with
  266. databases: transaction management, concurrency control, queries,
  267. selective object materialization, etc. Below, the two solutions are
  268. addressed in turn.
  269.  
  270. There are two main techniques for the file system solution. The first
  271. involves using #. to compile the data into a file.  The second
  272. produces an ASCII representation which, when evaluated, will reproduce
  273. an equivalent set of data.
  274.  
  275. If the data you wish to save is stored in the variable *hash-table*,
  276. create a file containing just the lines
  277.         (in-package "YOUR-PACKAGE")
  278.         (setq *hash-table* '#.*hash-table*)
  279. and compile it. The #. macro performs read-time evaluation of the
  280. expression following the dot, and so this compiles the data into the
  281. file. You may then load the file to restore the data. However, the
  282. resulting binary file is not portable between Lisp implementations,
  283. and sometimes not even for the same Lisp on different platforms. Also,
  284. some Lisps will treat the data as constant, and place it on pages in
  285. memory that are marked read-only (after it is loaded). If one tries to
  286. later modify the data, these Lisps will signal an error. Lucid CL only
  287. puts such constants in a read-only area when they appear inside
  288. functions, so this should be safe. Allegro CL doesn't seem to complain
  289. about modification if the data is a cons. DEC's VAXLisp, however, has
  290. problems with #. circular structures in .fas files. MCL seems to work
  291. well with using #. to save data (and even functions) to a file.
  292.  
  293. The other technique is to produce an ASCII representation of the Lisp
  294. objects which may then be saved to a file. To reproduce the data, one
  295. can load (or compile and load) the file. This technique is portable
  296. between different Lisps and platforms. Unfortunately, the resulting
  297. data is not necessarily EQ to the original. Kerry Koitzsch's
  298. save-object.lisp package is included in the Lisp Utilities Repository,
  299.    ftp.cs.cmu.edu:/user/ai/lang/lisp/code/ext/save_obj/
  300. The Lisp Utilities Repository is described in detail in the answer to
  301. question [6-1]. 
  302.  
  303. See also the discussion of MAKE-LOAD-FORM and MAKE-LOAD-FORM-SAVING-SLOTS 
  304. in CLtL2.
  305.  
  306. Here are some solutions to object persistence that use databases instead
  307. of file systems.
  308.  
  309. Free Persistent Object Storage systems include: 
  310.  
  311.    WOOD (William's Object Oriented Database) is a simple persistent
  312.    object store for MCL 2.0.x & MCL 3.0, written by Bill St. Clair
  313.    <bill@cambridge.apple.com>.  Its goal is to provide a way to
  314.    save/restore Lisp objects to/from disk. It is available by anonymous
  315.    ftp from from ftp://ftp.digitool.com:/pub/mcl2/contrib/wood/.
  316.    Send bug reports to bug-wood@cambridge.apple.com. To be added to the
  317.    mailing list, send mail to info-wood-request@cambridge.apple.com.
  318.  
  319.    PCLOS is a persistent object store for CLOS that was implemented using
  320.    CLOS's metaobject protocol. It allowed multiple different storage
  321.    facilities to be used. The benefit of this approach is it lets you use
  322.    different storage facilities depending on your needs, ranging from a
  323.    full-blown database with concurrency control and recovery to a very
  324.    fast store that trades speed for functionality. For example, an
  325.    in-memory store that saves its state to disk periodically can be much
  326.    faster than traditional databases, but risks loss of data due to
  327.    crashes. Unfortunately, PCLOS was built on a very old version of CLOS,
  328.    so it is unusable in its current form, and there are no plans to
  329.    update it. The introductory MOP chapter in the book "Object-Oriented
  330.    Programming: The CLOS Perspective" (see [5-1] above) explains how to
  331.    do the rewrite in principle and shows how the CLOS MOP was used for
  332.    object persistence in PCLOS. See also 
  333.       1. Andreas Paepcke, "PCLOS: A Flexible Implementation of CLOS 
  334.          Persistence", in Proceedings of ECOOP-88, S. Gjessing and K.
  335.          Nygaard, editors, Lecture Notes in Computer Science, Springer
  336.          Verlag, pages 374-389, 1988.  [Explains the PCLOS architecture.]
  337.       2. Andreas Paepcke, "PCLOS: A Critical Review", in OOPSLA-89, 1989. 
  338.          [Uses PCLOS as a roadmap through the issues of object persistence.]
  339.       3. Andreas Paepcke, "PCLOS Reference Manual", Hewlett-Packard
  340.          Laboratories, December, 1991.
  341.    For more information about PCLOS, write to Andreas Paepcke
  342.    <paepcke@parc.xerox.com>. 
  343.  
  344.    GBB (see [6-3]) is a blackboard architecture with persistence of a
  345.    sort. Every object in GBB is held in RAM, and there are dump and
  346.    restore functions. It handles distributed object delivery and
  347.    function-call triggering of receiving processes.
  348.  
  349. Commercial Persistent Object Storage systems include: 
  350.  
  351.    AllegroStore is a high-performance object-oriented database management
  352.    system from Franz. It offers Allegro CL users persistent object
  353.    storage with very fast retrieval and update of object data.  It
  354.    provides query processing and transaction-based operation. Built on a
  355.    multi-client, multi-server architecture, it permits concurrent access
  356.    over a network to objects by multiple independent processes.  It uses
  357.    the ObjectStore ODBMS from Object Design Inc, and thus has both Lisp
  358.    and C interfaces and is also very fast.  The CLOS interface is based
  359.    on MOP, with dynamic class/schema modification and redefinition.
  360.    AllegroStore can handle large-scale applications with minimal impact
  361.    on performance. It uses page-faulting and page-locking mechanisms
  362.    instead of object locking, providing high throughput and low overhead
  363.    for concurrent access by multiple users.  Standard database features
  364.    include deadlock detection, referential integrity, and inverse
  365.    functions.  Exception handling is integrated into the Lisp condition
  366.    system. AllegroStore runs on Sparc, SGI, HP, RS/6000, and
  367.    MS-Windows/NT systems.  For more information, send email to
  368.    info@franz.com, write to Franz Inc., 1995 University Avenue, Berkeley,
  369.    CA 94704, call 1-800-333-7260, 510-548-3600, fax 510-548-8253, or
  370.    telex 340179 WUPUBTLXSFO.
  371.  
  372.    ITASCA ODBMS V2.2 is a distributed active object database management
  373.    system. ITASCA allows clients to transparently access data that is
  374.    distributed among multiple servers.  ITASCA supports full dynamic
  375.    schema modification that can be performed during any phase of the
  376.    software lifecycle.  Applications written in dissimilar and
  377.    incompatible languages, such as C/C++ and CLOS, can share objects through
  378.    ITASCA. ITASCA stores methods inside the database, promoting
  379.    reusability and maintainability.  ITASCA is based on work at MCC's
  380.    Object-Oriented and Distributed Systems Lab on the ORION system. For
  381.    more information, write to Itasca Systems, Inc., 7850 Metro Parkway,
  382.    Minneapolis, MN 55425, sales@itasca.com, 612-832-0409, fax 612-851-3157.
  383.    [Clint Hyde has written a MOP CLOS interface to Itasca, which has some
  384.    features not present in their interface. For a free copy of his source
  385.    code, send him mail to chyde@bbn.com.]
  386.  
  387.    LispWorks (from Harlequin), in addition to providing a traditional
  388.    SQL-based interface to relational databases, also provides a CLOS/SQL
  389.    interface, which is an object-oriented access layer that enables SQL
  390.    data to be manipulated as objects within Lisp, even though those objects
  391.    are not manifest in the database.  This can be especially useful when
  392.    importing data from and exporting data to a database provided by another
  393.    (usually non-Lisp-based) application that already uses a relational
  394.    database to achieve data persistence.
  395.  
  396.    Statice is a commercial product from Symbolics, that provides a
  397.    powerful persistent ODBMS. It runs on Symbolics Lisp Machines. 
  398.  
  399. ----------------------------------------------------------------
  400. Subject: [5-5] Given the name of a class, how can I get the names
  401.                of its slots?     
  402.  
  403. (defun class-slot-names (class-name)
  404.   "Given a CLASS-NAME, returns a list of the slots in the class."
  405.   (mapcar #'clos:slot-definition-name
  406.           (clos:class-slots (find-class class-name))))
  407.  
  408. (defmethod class-slot-names ((instance standard-object))
  409.   "Given an INSTANCE, returns a list of the slots in the instance's class."
  410.   (mapcar #'clos:slot-definition-name
  411.           (clos:class-slots (class-of instance))))
  412.  
  413. You can use CLASS-DIRECT-SLOTS instead of CLASS-SLOTS if you don't
  414. want inherited slots. Note that these functions are from the
  415. meta-object protocol specified in the original X3J13 draft spec
  416. (document X3J13/88-003), and may not be supported by all Lisps.
  417.  
  418. ----------------------------------------------------------------
  419. Subject: [5-6] Free CLOS software.
  420.  
  421. Software Repositories:
  422.  
  423.    The CLOS code repository is available by anonymous ftp to
  424.    nervous.cis.ohio-state.edu:/pub/lispusers/clos/ [128.146.61.200]
  425.    If you've got code you'd like to add to the repository, send
  426.    mail to Arun Welch, commonloops-request@cis.ohio-state.edu.
  427.    The CLOS code repository includes dag.lisp.Z and 3DGeometry.lisp.
  428.  
  429. ----------------------------------------------------------------
  430. Subject: [5-7] Common CLOS Blunders
  431.  
  432. This question is based on a document written by Marty Hall
  433. <hall@aplcenmp.apl.jhu.edu>. The full text of Marty's
  434. "Introduction to CLOS" handout is available by anonymous ftp from
  435.    ftp.cs.cmu.edu:/user/ai/lang/lisp/doc/intro/closintr.tgz
  436.  
  437. This question lists a variety of common errors that occur when writing
  438. CLOS code. It is extremely useful to glance through this list when
  439. debugging CLOS code.
  440.  
  441. [A] Omitting a set of parentheses around the arglist in DEFMETHOD.
  442.  
  443.     For example, writing 
  444.        (defmethod Area (Sq Square) ...)
  445.     instead of
  446.        (defmethod Area ((Sq Square)) ...)
  447.  
  448.     Lisp will accept the former, and think that you have two
  449.     unspecialized arguments instead of one argument specialized as a
  450.     Square. 
  451.  
  452. [B] Missing parentheses around the slot definition list in DEFCLASS.
  453.  
  454.     For example, writing
  455.        (defclass Rectangle (Polygon)
  456.      (Width ...)
  457.      (Height ...)) 
  458.     instead of
  459.        (defclass Rectangle (Polygon)
  460.      ((Width ...)
  461.       (Height ...)))
  462.  
  463.     Lisp will not accept the former, but the error message doesn't
  464.     always clearly identify the problem.
  465.  
  466. [C] Forgetting to include an empty slot definition list if you don't
  467.     define local slots in DEFCLASS.
  468.  
  469.     For example, writing 
  470.        (defclass Square (Rectangle)) 
  471.     instead of
  472.        (defclass Square (Rectangle) ())
  473.     Lisp will not accept the former.
  474.  
  475. [D] Referring to the class name instead of the instance variable in
  476.     DEFMETHOD. 
  477.  
  478.     For example, writing 
  479.        (defmethod Area ((Sq Square)) 
  480.      (* (Width Square) (Width Square))) 
  481.     instead of
  482.        (defmethod Area ((Sq Square)) 
  483.      (* (Width Sq) (Width Sq)))
  484.  
  485.     Lisp may give you a warning about an unknown free variable, but
  486.     probably won't even do that if you type the defmethod directly into
  487.     the Lisp Listener (Lucid doesn't). So you might not encounter a
  488.     problem until run-time.
  489.  
  490. [E] Forgetting that accessors are functions and thus could conflict
  491.     with built-in function names.
  492.  
  493.     For example, writing
  494.        (defclass Graphical-Object ()
  495.      ((Position :accessor Position)))
  496.     will signal an error, since you cannot redefine the built-in
  497.     POSITION function.  
  498.  
  499. [F] Putting the new value last instead of first in the definition of a 
  500.     SETF method. 
  501.  
  502.     For example, writing 
  503.        (defmethod (setf Area) ((Sq Square) (New-Area number))
  504.      (setf (Width Sq) (sqrt New-Area))) 
  505.     instead of
  506.        (defmethod (setf Area) ((New-Area number) (Sq Square))
  507.      (setf (Width Sq) (sqrt New-Area)))
  508.  
  509.    Lisp will accept the former, causing users to be later puzzled as
  510.    to why (setf (Area Square-1) 10) doesn't work.
  511.  
  512. [G] Putting the new value last instead of first in a call to a :writer
  513.     method.  
  514.  
  515.     For example, given
  516.        (defclass Circle () 
  517.      ((Radius :reader Radius :writer Set-Radius :initform 5)))
  518.        (setq Circle-1 (make-instance 'Circle))
  519.     and writing
  520.        (Set-Radius Circle-1 10)
  521.     instead of
  522.        (Set-Radius 10 Circle-1)
  523.  
  524. [H] Confusion about documentation strings in DEFMETHOD. 
  525.  
  526.     People often write code like
  527.        (defmethod Area ((Rect Rectangle))
  528.      "WIDTH times HEIGHT of the rectangle"
  529.      (* (Width Rect) (Height Rect)))
  530.     without clearly thinking about what this might mean.  Some people
  531.     think it will make a documentation string on the generic function that
  532.     can be retrieved by calling (DOCUMENTATION 'Area 'function) or the
  533.     equivalent emacs keystrokes. Others vaguely expect it to make a doc
  534.     string on each separate method, and that the call to DOCUMENTATION
  535.     will somehow be able to automagically figure out which method it
  536.     applies to.
  537.  
  538.     In fact, Lisp won't complain about this code, with the result that the
  539.     documentation is added to the method *object*, which beginners
  540.     probably know nothing about. 
  541.  
  542.     Use the :documentation entry in defgeneric to add a documentation
  543.     string to the generic function.
  544.  
  545. [I] Invalid :initargs are accepted by MAKE-INSTANCE.
  546.  
  547.     Many Lisp implementations will accept unknown keyword initargs without
  548.     complaint, even at the highest safety settings. 
  549.  
  550.     So the following code, which includes a typo of :SLOT1 instead of
  551.     :SLOT-1 in the call to make-instance
  552.        (defclass Foo ()
  553.     ((Slot-1 :accessor Slot-1 :initarg :Slot-1 :initform 5)))
  554.  
  555.        (setq Test (make-instance 'Foo :Slot1 10)) 
  556.     will not produce an error message, with the result that
  557.     (Slot-1 Test) returns 5, not 10.
  558.  
  559.     This is a bug in the implementation; all implementations are
  560.     supposed to flag this as an error. 
  561.  
  562. [J] Forgetting the class must exist before any method can specialize upon it. 
  563.  
  564.     Lisp programmers are used to being able to define functions in any
  565.     order, where even if FOO calls BAR, FOO can be defined first. But doing
  566.        (defmethod Area ((Rect Rectangle)) ...)
  567.        (defclass Rectangle (Polygon) ...)
  568.     is illegal. You have to define the class first.
  569.  
  570.     If while trying to debug the problem, you define the class by
  571.     evaluating the definition without reordering the code to put the
  572.     class first, you'll only run into problems later the next time you
  573.     try to recompile the code from scratch.
  574.  
  575.     Many experienced programmers put each class definition in its own
  576.     file at the top of the file, with methods for that class after it
  577.     in the file. Others opt to put all the class definitions for a
  578.     program in a single file that is loaded first, with methods in files
  579.     that are loaded later.
  580.  
  581. [K] Changing a method to apply to a more general class does not
  582.     supersede previous method. 
  583.  
  584.     For example, suppose a user writes
  585.        (defmethod Half-Area ((Rect Filled-Rectangle))
  586.      (/ (Area Rect) 2))
  587.     and then notices that this functionality could apply to all
  588.     Rectangles, not just Filled-Rectangles. They might then change the
  589.     class referenced in this method, under the specious intuition that by
  590.     changing the old defintion, they are replacing it. In fact, they are
  591.     actually adding a new, less-specific method.
  592.  
  593.     Now suppose that later on, they change this new method (in this
  594.     example, by adding a call to FLOAT to avoid returning a ratio),
  595.        (defmethod Half-Area ((Rect Rectangle))
  596.      (float (/ (Area Rect) 2)))
  597.     If they test it on an instance of Filled-Rectangle, they will be
  598.     puzzled as to why their new definition appears to have not taken
  599.     effect. But because the old definition specialized to Filled-Rectangle 
  600.     still exists, they're actually getting the old, more-specific definition.
  601.  
  602.     Moreover, the next time they restart a fresh Lisp and recompile
  603.     the code, the problem will magicly disappear, since the old
  604.     definition is no longer in the code. 
  605.  
  606. ----------------------------------------------------------------
  607. ;;; *EOF*
  608.  
  609.