|Adam Petersen - Software Development Pages, Book Reviews Section|
Object-Oriented Programming in Common
Lisp: A Programmer's Guide to CLOS
Every now and then there’s a newsgroup-posting mentioning just how elegantly CLOS (Common Lisp Object System) solves some particularly nasty problem. I decided that it was finally time for me to get a deeper understanding of the CLOS. In retrospect it has been a very rewarding experience and this book served as a great guide.
First a little background. The CLOS was a unification of the different efforts to support object-oriented programming in Lisp and was later incorporated into the ANSI standard of Common Lisp. Although this book predates the standard with some years, only minor things have actually changed and the book is still referred to as the best CLOS introduction available.
What first struck me is how CLOS turns things inside-out in comparison with mainstream languages like C++ and Java. Unlike these languages where methods are defined within the classes CLOS separates them. This turns out to be an extremely flexible model. The first implication is that free-standing functions and methods are called with a uniform syntax, which makes it possible to pass methods as arguments to higher-order functions (in C++ I've been using boost.function to achieve a similar effect). Polymorphism in CLOS starts with generic functions. A generic function is an abstract function, an interface. Following the signature established by the generic function, methods may be defined specializing the type of the arguments on different classes. And here's the really cool feature: a method may be specialized on any number of arguments, so called multi-methods. In C++ and Java we're limited to single-dispatch and have to resort to design patterns like Visitor to simulate CLOS behavior. Yet, even with Visitor, for all practical purposes we are limited to two parameters. Not so with CLOS.
CLOS also allows :before, :after, and :around qualifications of methods. The qualifications do exactly what can be expected; for example, a :before method is called before its primary method. Keene demonstrates how these different kinds of methods supports clear separation of different responsibilities. This makes a design open for extensions without the need to modify existing code. For example, an :after method could be used to implement a notification mechanism à la the Observer pattern.
This book illustrates how all these powerful features are used in practice by walking us through the implementation of multi-threading locks and a stream library. These case studies do an excellent job of tying the pieces of theory together. Their designs are elegant and the accompanying discussions teach good OO design.
As if the generic dispatch of CLOS wasn't challenging enough, the dynamic nature of Lisp allows for further really cool techniques. For example, a class may be modified at run-time and existing objects are transformed according to the new class definition! CLOS even allows us to specify exactly how this transformation shall be done. I guess that it is features like this that make Common Lisp such a good choice for server side programming. Imaging a huge online-store; using these techniques, its software can be modified live transparently to shopping customers.
The book descibes a paradigm very different to the popular mainstream languages and I would recommend it to anyone interested in object-orientation as a mind-bending experience. For its CLOS coverage I cannot think of a better book. The minor criticism I have is that the text is rather dry. On the other hand it makes up a strange but interesting contrast to the exiting subject of CLOS.
Reviewed May 2006
|©2005 Adam Petersenfirstname.lastname@example.org|