Lisp and Symbolic Computation, 2, I63 165 (1989) ,~) 1989 Kluwer Academic Publishers Manufactured in The Netherlands.
Book Review Object-Oriented Programming in Common LISP: A Programmer's Guide to CLOS Sonya E. Keene, Massachusetts: Addison-Westey~ 1989.
Object-Oriented Programming in Common LISP is a very useful introduction to the new Common LISP Object System (CLOS). CLOS is a new object oriented programming system that combines many of the best features found in previous systems. It provides a clean and consistent semantic model in an extensible framework that can be efficiently implemented on stock hardware. The CLOS standard was recently approved as part of ANSI Standard Common LISP by the ANSI X3J13 committee. The standardization of the various dialects of LISP into Common LISP had the effect of dramatically improving the quality of the LISP that most programmers had to work with. The inclusion of CLOS in Common LISP should have the same effect on object oriented programming. CLOS provides one more standardized tool available to LISP programmers. It is a tool that is particularly useful for the construction of medium to large programs that are written by multiple authors and are intended to last a long time. It is generally easier to understand and extend a well designed object oriented program than a conventional program. These considerations make learning CLOS an important goal for Common LISP programmers. Keene's book is intended as an introduction both to the art of object oriented programming in general and to the characteristics of CLOS. It does a good job addressing both of these goals. Its primary audience will be experienced LISP programmers, although some attempt is made to make the book accessible to n o n LISP programmers. But to the latter group, the explanations of LISP are not thorough enough to make the book useful. The overall structure of the book is excellent. The first and second chapters describe some of the benefits of object oriented programming and how CLOS extends Common LISP. This serves as a motivation for LISP programmers to learn CLOS. The second chapter also gives an excellent intuitive description of the basic CLOS concepts of classes, instances, slots, inheritance, generic functions and methods. This description includes some pictures which clearly demonstrate the CLOS conceptual model. As the book progresses, it introduces more detail into the conceptual model and describes the functions that are used to implement those features. Each function is introduced in the context of writing a specific example. The book also anticipates reader questions by including references to later sections which fill in details that were suppressed for the purposes of explaining a particular function. Summaries of important points are set off from the surrounding text in tables and boxes that are easy to
164
MCCONNELL
find. These summaries are particularly helpful when the book is used as a reference. The appendix on the syntax of functions points to these summary boxes so that they can easily be found. There are a number of short example programs, plus three long examples used to demonstrate CLOS programming techniques. The author does a good job of explaining how all the incrementally developed parts fit together in the completed examples. There is some attempt to make the examples accessible to the non-LISP programmer through explanations of LISP concepts like the lambda list. But there is not enough explanation for non-LISP programmers and more than enough for readers who are already LISP programmers. Some of the shorter examples will run in any standard Common LISP and CLOS implementation. The three full examples (locks, remote evaluation and streams) will not. Each example relies on functions that are not part of Common LISP, like S Y S : % P O I N T E R and W I T H O U T - P R O C E S S - P R E E M P T I O N . The purpose of these extra functions is documented, so it is possible for a reader to convert them to the system-dependent constructs provided by a particular implementation, or to write a dummy functions to use in place of the real function. The author says she felt that the goal of demonstrating large real world applications conflicted with the goal of writing pure Common LISP. This is a strange position to take on the usefulness of Common LISP and CLOS! The more likely reason these examples were chosen is that they already existed in applications where the author works. The book would be better with examples that would run in standard Common LISP and that were more typical of applications LISP users rather than LISP manufacturers write. With a little more effort such examples could have been developed. Some better examples might have been the construction of a simple simulation system, or the definition of a make system for controlling the load and compile dependencies between files. Either of these could demonstrate the same principles as Keene's examples, but in a portable fashion. The first example would be typical of many real world simulation systems and the second example would provide an extension to Common LISP that would be portable. One of the real strengths of the book is that it includes some of the lore of object oriented programming. Object oriented programming is not a magic technique whose mere use is guaranteed to make large programs easy to maintain and extend. There is a whole body of knowledge about how to structure an application to take advantage of the tools provided by CLOS. This book brings out some of these techniques both through their use in the examples and through explicit discussions of why one approach is better than another. For example, the reader is taught how to structure inheritance, how to define external and internal protocols and how to use method combination. The most important CLOS functions are well covered in this book. The coverage includes parts of CLOS that have no counterpart in most earlier object oriented LISP systems, such as multi-methods, individual methods, methods on LISP data structures, and the redefinition of CLOS elements. The final chapter gives an overview of the CLOS design goals and the language features which they led to. The CLOS
BOOK REVIEW
165
meta-object protocol is also discussed. Currently this protocol remains an open part of the specification. When it is completed, researchers will be able to experiment with alternate object oriented models within the CLOS framework. No knowledge of the meta-object protocol is needed to use CLOS for most purposes, so its summary description is not a drawback. There is a glossary which describes CLOS terminology and an appendix that describes the syntax of each function. The glossary is nice since it makes explicit the terminology that CLOS standardizes; some of this terminology differs from that of other object oriented systems. In the appendix, each description contains references to the places in the book where topics related to the function are discussed. The appendix makes Object-Oriented Programming in Common L I S P an excellent reference for the CLOS programmer since it ties the detailed syntax of each function to the extended discussions and summaries found in the text. There is another appendix that describes functions that are not discussed in this book: functions that define local generic functions in the style of F L E T and LABELS, functions that are called in error situations, functions that define new method combination types, and some other miscellaneous functions. Several of the latter, including D O C U M E N T A T I O N , S L O T - M A K U N B O U N D , and S L O T - E X I S T S - P should have been included in the text. The other functions will rarely be used in typical applications, but it would have been helpful if the syntax of these functions and some brief description--at least at the level of the Programmer's Guide part of the CLOS specification--were included in the book. The index and bibliography are adequate. Even though this is not a theoretical text, it would be helpful if it were tied to the larger tradition of object oriented programming as found in other languages through a more comprehensive bibliography. Object-Oriented Programming in Common L I S P is the first book on CLOS. As such it will provide the first introduction for many Common LISP programmers to both object oriented programming and the CLOS standard. Despite a few flaws, it is definitely a worthy introduction to both topics. In addition to being a good tutorial, it is a useful reference for the parts of CLOS that most programmers will use. CHRIS McCONNELL Computer Science Department Cornegie Mellon Pittsburgh, Pennsylvania