This book is about a new approach to programming language design, in which these two demands of elegance and efficiency are viewed as compatible, not conflicting. Our goal is the development of languages that are as clean as the purest theoretical designs, but that make no compromises on performance or control over implementation.
The way in which we have achieved elegance and efficiency jointly is to base language design on metaobject protocols. Metaobject protocols are interfaces to the language that give users the ability to incrementally modify the language's behavior and implementation, as well as the ability to write programs within the language.
Languages that incorporate metaobject protocols blur the distinction between language designer and language user. Traditionally, designers are expected to produce languages with well-defined, fixed behaviors (or ``semantics''). Users are expected to treat these languages as immutable black-box abstractions, and to derive any needed flexibility or power from constructs built on top of them. This sharp division is thought to constitute an appropriate division of labor. Programming language design is viewed as a difficult, highly-specialized art, inappropriate for average users to engage in. It is also often assumed that a language design must be rigid in order to support portable implementations, efficient compilers, and the like. The metaobject protocol approach, in contrast, is based on the idea that one can and should ``open languages up,'' allowing users to adjust the design and implementation to suit their particular needs. In other words, users are encouraged to participate in the language design process. If handled properly, opening up the language design need not compromise program portability or implementation efficiency.
In a language based upon our metaobject protocols, the language implementation itself is structured as an object-oriented program. This allows us to exploit the power of object-oriented programming techniques to make the language implementation adjustable and flexible. In effect, the resulting implementation does not represent a single point in the overall space of language designs, but rather an entire region within that space.
The protocols followed by this object-oriented program serve two important functions. First, they are used by the designers to specify a distinguished point in that region, corresponding to the language's default behavior and implementation. Second, they allow users to create variant languages, using standard techniques of subclassing and specialization. In this way, users can select whatever point in the region of language designs best serves their needs.
Our development of the metaobject protocol approach has emerged hand-in-hand with our involvement, over the past several years, in the design of the Common Lisp Object System (CLOS) CLOS is a high-level object-oriented language designed as part of the ANSI Common Lisp standard. That project brought us face to face with many of the classic problems of high-level languages, including the need for compatibility with existing languages, special extensions for particular projects, and efficiency. Our effort to deal with these problems led us to develop the approach to language design based on metaobject protocols and to implement a first practical instance, a metaobject protocol for CLOS.
The purpose of this book is twofold. First, in Part I, we present metaobject protocol design by gradually deriving a simplified metaobject protocol for CLOS. Because we expect the notion of a metaobject protocol itself to evolve, we not only present the approach as we understand it today, but also point towards open issues and directions for further development.
In Part II we provide a detailed and complete description of a particular metaobject protocol we have designed for CLOS. This second CLOS metaobject protocol can be incorporated into production CLOS implementations and used for writing production-quality code.
The work reported in this book synthesizes a number of concerns and approaches from different parts of the computer science field. As a result we hope it will be of interest to a wide spectrum of the community:
Augmenting a language with a metaobject protocol does not need to be a radical change. In many cases, problems with an existing language or implementation can be improved by gradually introducing metaobject protocol features. Also, compiler, debugger, and programming environment features can often be recast as metaobject protocols, with concomitant simplifications in their design, implementation, and documentation.