Replace $letrec with $rec
[bpt/guile.git] / doc / ref / goops.texi
index 06cf816..ce0b76b 100644 (file)
@@ -1,6 +1,6 @@
 @c -*-texinfo-*-
 @c This is part of the GNU Guile Reference Manual.
-@c Copyright (C)  2008, 2009
+@c Copyright (C)  2008, 2009, 2011
 @c   Free Software Foundation, Inc.
 @c See the file guile.texi for copying conditions.
 
@@ -17,607 +17,398 @@ Guile
 
 @goops{} is the object oriented extension to @guile{}. Its
 implementation is derived from @w{STk-3.99.3} by Erick Gallesio and
-version 1.3 of Gregor Kiczales @cite{Tiny-Clos}.  It is very close in
-spirit to CLOS, the Common Lisp Object System (@cite{CLtL2}) but is
-adapted for the Scheme language.  While GOOPS is not compatible with any
-of these systems, GOOPS contains a compatibility module which allows for
-execution of STKlos programs.
-
-Briefly stated, the @goops{} extension gives the user a full object
-oriented system with multiple inheritance and generic functions with
-multi-method dispatch.  Furthermore, the implementation relies on a true
-meta object protocol, in the spirit of the one defined for CLOS
-(@cite{Gregor Kiczales: A Metaobject Protocol}).
+version 1.3 of Gregor Kiczales' @cite{Tiny-Clos}.  It is very close in
+spirit to CLOS, the Common Lisp Object System, but is adapted for the
+Scheme language.
 
-@menu
-* Quick Start::
-* Tutorial::
-* Reference Manual::
-* MOP Specification::
-@end menu
-
-@node Quick Start
-@section Quick Start
+@goops{} is a full object oriented system, with classes, objects,
+multiple inheritance, and generic functions with multi-method
+dispatch.  Furthermore its implementation relies on a meta object
+protocol --- which means that @goops{}'s core operations are themselves
+defined as methods on relevant classes, and can be customised by
+overriding or redefining those methods.
 
-To give an immediate flavour of what GOOPS can do, here is a very
-quick introduction to its main operations.
+To start using @goops{} you first need to import the @code{(oop goops)}
+module.  You can do this at the Guile REPL by evaluating:
 
-To start using GOOPS, load the @code{(oop goops)} module:
-
-@smalllisp
+@lisp
 (use-modules (oop goops))
-@end smalllisp
-
-We're now ready to try some basic GOOPS functionality.
+@end lisp
+@findex (oop goops)
 
 @menu
-* Methods::
-* User-defined types::
-* Asking for the type of an object::
+* Copyright Notice::
+* Class Definition::
+* Instance Creation::  
+* Slot Options::
+* Slot Description Example::
+* Methods and Generic Functions::           
+* Inheritance::                 
+* Introspection::
+* GOOPS Error Handling::
+* GOOPS Object Miscellany::
+* The Metaobject Protocol::
+* Redefining a Class::
+* Changing the Class of an Instance::
 @end menu
 
-@node Methods
-@subsection Methods
+@node Copyright Notice
+@section Copyright Notice
 
-A GOOPS method is like a Scheme procedure except that it is
-specialized for a particular set of argument types.
-
-@lisp
-(define-method (+ (x <string>) (y <string>))
-  (string-append x y))
+The material in this chapter is partly derived from the STk Reference
+Manual written by Erick Gallesio, whose copyright notice is as follows.
 
-(+ "abc" "de") @result{} "abcde"
-@end lisp
+Copyright © 1993-1999 Erick Gallesio - I3S-CNRS/ESSI <eg@@unice.fr>
+Permission to use, copy, modify, distribute,and license this
+software and its documentation for any purpose is hereby granted,
+provided that existing copyright notices are retained in all
+copies and that this notice is included verbatim in any
+distributions.  No written agreement, license, or royalty fee is
+required for any of the authorized uses.
+This software is provided ``AS IS'' without express or implied
+warranty.
 
-If @code{+} is used with arguments that do not match the method's
-types, Guile falls back to using the normal Scheme @code{+} procedure.
+The material has been adapted for use in Guile, with the author's
+permission.
 
-@lisp
-(+ 1 2) @result{} 3
-@end lisp
 
+@node Class Definition
+@section Class Definition
 
-@node User-defined types
-@subsection User-defined types
+A new class is defined with the @code{define-class} syntax:
 
+@findex define-class
+@cindex class
 @lisp
-(define-class <2D-vector> ()
-  (x #:init-value 0 #:accessor x-component #:init-keyword #:x)
-  (y #:init-value 0 #:accessor y-component #:init-keyword #:y))
+(define-class @var{class} (@var{superclass} @dots{})
+   @var{slot-description} @dots{}
+   @var{class-option} @dots{})
+@end lisp
 
-@group
-(use-modules (ice-9 format))
+@var{class} is the class being defined.  The list of @var{superclass}es
+specifies which existing classes, if any, to inherit slots and
+properties from.  @dfn{Slots} hold per-instance@footnote{Usually --- but
+see also the @code{#:allocation} slot option.} data, for instances of
+that class --- like ``fields'' or ``member variables'' in other object
+oriented systems.  Each @var{slot-description} gives the name of a slot
+and optionally some ``properties'' of this slot; for example its initial
+value, the name of a function which will access its value, and so on.
+Class options, slot descriptions and inheritance are discussed more
+below.
+@cindex slot
+
+@deffn syntax define-class name (super @dots{}) @
+              slot-definition @dots{} class-option @dots{}
+Define a class called @var{name} that inherits from @var{super}s, with
+direct slots defined by @var{slot-definition}s and @var{class-option}s.
+The newly created class is bound to the variable name @var{name} in the
+current environment.
 
-(define-method (write (obj <2D-vector>) port)
-  (display (format #f "<~S, ~S>" (x-component obj) (y-component obj))
-           port))
+Each @var{slot-definition} is either a symbol that names the slot or a
+list,
 
-(define v (make <2D-vector> #:x 3 #:y 4))
+@example
+(@var{slot-name-symbol} . @var{slot-options})
+@end example
 
-v @result{} <3, 4>
-@end group
+where @var{slot-name-symbol} is a symbol and @var{slot-options} is a
+list with an even number of elements.  The even-numbered elements of
+@var{slot-options} (counting from zero) are slot option keywords; the
+odd-numbered elements are the corresponding values for those keywords.
 
-@group
-(define-method (+ (x <2D-vector>) (y <2D-vector>))
-  (make <2D-vector>
-        #:x (+ (x-component x) (x-component y))
-        #:y (+ (y-component x) (y-component y))))
+Each @var{class-option} is an option keyword and corresponding value.
+@end deffn
 
-(+ v v) @result{} <6, 8>
-@end group
-@end lisp
+As an example, let us define a type for representing a complex number
+in terms of two real numbers.@footnote{Of course Guile already
+provides complex numbers, and @code{<complex>} is in fact a predefined
+class in GOOPS; but the definition here is still useful as an
+example.}  This can be done with the following class definition:
 
-@node Asking for the type of an object
-@subsection Types
+@lisp
+(define-class <my-complex> (<number>)
+   r i)
+@end lisp
 
-@example
-(class-of v) @result{} #<<class> <2D-vector> 40241ac0>
-<2D-vector>  @result{} #<<class> <2D-vector> 40241ac0>
-(class-of 1) @result{} #<<class> <integer> 401b2a98>
-<integer>    @result{} #<<class> <integer> 401b2a98>
+This binds the variable @code{<my-complex>} to a new class whose
+instances will contain two slots.  These slots are called @code{r} and
+@code{i} and will hold the real and imaginary parts of a complex
+number. Note that this class inherits from @code{<number>}, which is a
+predefined class.@footnote{@code{<number>} is the direct superclass of
+the predefined class @code{<complex>}; @code{<complex>} is the
+superclass of @code{<real>}, and @code{<real>} is the superclass of
+@code{<integer>}.}
 
-(is-a? v <2D-vector>) @result{} #t
-@end example
+Slot options are described in the next section.  The possible class
+options are as follows.
 
-@node Tutorial
-@section Tutorial
-@include goops-tutorial.texi
+@deffn {class option} #:metaclass metaclass
+The @code{#:metaclass} class option specifies the metaclass of the class
+being defined.  @var{metaclass} must be a class that inherits from
+@code{<class>}.  For the use of metaclasses, see @ref{Metaobjects and
+the Metaobject Protocol} and @ref{Metaclasses}.
 
-@node Reference Manual
-@section Reference Manual
+If the @code{#:metaclass} option is absent, GOOPS reuses or constructs a
+metaclass for the new class by calling @code{ensure-metaclass}
+(@pxref{Class Definition Protocol,, ensure-metaclass}).
+@end deffn
 
-This chapter is the GOOPS reference manual.  It aims to describe all the
-syntax, procedures, options and associated concepts that a typical
-application author would need to understand in order to use GOOPS
-effectively in their application.  It also describes what is meant by
-the GOOPS ``metaobject protocol'' (aka ``MOP''), and indicates how
-authors can use the metaobject protocol to customize the behaviour of
-GOOPS itself.
+@deffn {class option} #:name name
+The @code{#:name} class option specifies the new class's name.  This
+name is used to identify the class whenever related objects - the class
+itself, its instances and its subclasses - are printed.
 
-For a detailed specification of the GOOPS metaobject protocol, see
-@ref{MOP Specification}.
+If the @code{#:name} option is absent, GOOPS uses the first argument to
+@code{define-class} as the class name.
+@end deffn
 
-@menu
-* Introductory Remarks::
-* Defining New Classes::
-* Creating Instances::
-* Accessing Slots::
-* Creating Generic Functions::
-* Adding Methods to Generic Functions::
-* Invoking Generic Functions::
-* Redefining a Class::
-* Changing the Class of an Instance::
-* Introspection::
-* Miscellaneous Functions::
-@end menu
 
-@node Introductory Remarks
-@subsection Introductory Remarks
+@node Instance Creation
+@section Instance Creation and Slot Access
 
-GOOPS is an object-oriented programming system based on a ``metaobject
-protocol'' derived from the ones used in CLOS (the Common Lisp Object
-System), tiny-clos (a small Scheme implementation of a subset of CLOS
-functionality) and STKlos.
+An instance (or object) of a defined class can be created with
+@code{make}.  @code{make} takes one mandatory parameter, which is the
+class of the instance to create, and a list of optional arguments that
+will be used to initialize the slots of the new instance.  For instance
+the following form
 
-GOOPS can be used by application authors at a basic level without any
-need to understand what the metaobject protocol (aka ``MOP'') is and how
-it works.  On the other hand, the MOP underlies even the customizations
-that application authors are likely to make use of very quickly --- such
-as defining an @code{initialize} method to customize the initialization
-of instances of an application-defined class --- and an understanding of
-the MOP makes it much easier to explain such customizations in a precise
-way.  And in the long run, understanding the MOP is the key both to
-understanding GOOPS at a deeper level and to taking full advantage of
-GOOPS' power, by customizing the behaviour of GOOPS itself.
-
-Each of the following sections of the reference manual is arranged
-such that the most basic usage is introduced first, and then subsequent
-subsubsections discuss the related internal functions and metaobject
-protocols, finishing with a description of how to customize that area of
-functionality.
-
-These introductory remarks continue with a few words about metaobjects
-and the MOP.  Readers who do not want to be bothered yet with the MOP
-and customization could safely skip this subsubsection on a first reading,
-and should correspondingly skip subsequent subsubsections that are
-concerned with internals and customization.
-
-In general, this reference manual assumes familiarity with standard
-object oriented concepts and terminology.  However, some of the terms
-used in GOOPS are less well known, so the Terminology subsubsection
-provides definitions for these terms.
+@findex make
+@cindex instance
+@lisp
+(define c (make <my-complex>))
+@end lisp
 
-@menu
-* Metaobjects and the Metaobject Protocol::
-* Terminology::
-@end menu
+@noindent
+creates a new @code{<my-complex>} object and binds it to the Scheme
+variable @code{c}.
 
-@node Metaobjects and the Metaobject Protocol
-@subsubsection Metaobjects and the Metaobject Protocol
+@deffn generic make
+@deffnx method make (class <class>) initarg @dots{}
+Create and return a new instance of class @var{class}, initialized using
+@var{initarg} @enddots{}.
 
-The conceptual building blocks of GOOPS are classes, slot definitions,
-instances, generic functions and methods.  A class is a grouping of
-inheritance relations and slot definitions.  An instance is an object
-with slots that are allocated following the rules implied by its class's
-superclasses and slot definitions.  A generic function is a collection
-of methods and rules for determining which of those methods to apply
-when the generic function is invoked.  A method is a procedure and a set
-of specializers that specify the type of arguments to which the
-procedure is applicable.
+In theory, @var{initarg} @dots{} can have any structure that is
+understood by whatever methods get applied when the @code{initialize}
+generic function is applied to the newly allocated instance.
 
-Of these entities, GOOPS represents classes, generic functions and
-methods as ``metaobjects''.  In other words, the values in a GOOPS
-program that describe classes, generic functions and methods, are
-themselves instances (or ``objects'') of special GOOPS classes that
-encapsulate the behaviour, respectively, of classes, generic functions,
-and methods.
+In practice, specialized @code{initialize} methods would normally call
+@code{(next-method)}, and so eventually the standard GOOPS
+@code{initialize} methods are applied.  These methods expect
+@var{initargs} to be a list with an even number of elements, where
+even-numbered elements (counting from zero) are keywords and
+odd-numbered elements are the corresponding values.
 
-(The other two entities are slot definitions and instances.  Slot
-definitions are not strictly instances, but every slot definition is
-associated with a GOOPS class that specifies the behaviour of the slot
-as regards accessibility and protection from garbage collection.
-Instances are of course objects in the usual sense, and there is no
-benefit from thinking of them as metaobjects.)
+GOOPS processes initialization argument keywords automatically for slots
+whose definition includes the @code{#:init-keyword} option (@pxref{Slot
+Options,, init-keyword}).  Other keyword value pairs can only be
+processed by an @code{initialize} method that is specialized for the new
+instance's class.  Any unprocessed keyword value pairs are ignored.
+@end deffn
 
-The ``metaobject protocol'' (aka ``MOP'') is the specification of the
-generic functions which determine the behaviour of these metaobjects and
-the circumstances in which these generic functions are invoked.
+@deffn generic make-instance
+@deffnx method make-instance (class <class>) initarg @dots{}
+@code{make-instance} is an alias for @code{make}.
+@end deffn
 
-For a concrete example of what this means, consider how GOOPS calculates
-the set of slots for a class that is being defined using
-@code{define-class}.  The desired set of slots is the union of the new
-class's direct slots and the slots of all its superclasses.  But
-@code{define-class} itself does not perform this calculation.  Instead,
-there is a method of the @code{initialize} generic function that is
-specialized for instances of type @code{<class>}, and it is this method
-that performs the slot calculation.
+The slots of the new complex number can be accessed using
+@code{slot-ref} and @code{slot-set!}.  @code{slot-set!}  sets the value
+of an object slot and @code{slot-ref} retrieves it.
 
-@code{initialize} is a generic function which GOOPS calls whenever a new
-instance is created, immediately after allocating memory for a new
-instance, in order to initialize the new instance's slots.  The sequence
-of steps is as follows.
+@findex slot-set!
+@findex slot-ref
+@lisp
+@group
+(slot-set! c 'r 10)
+(slot-set! c 'i 3)
+(slot-ref c 'r) @result{} 10
+(slot-ref c 'i) @result{} 3
+@end group
+@end lisp
 
-@itemize @bullet
-@item
-@code{define-class} uses @code{make} to make a new instance of the
-@code{<class>}, passing as initialization arguments the superclasses,
-slot definitions and class options that were specified in the
-@code{define-class} form.
+The @code{(oop goops describe)} module provides a @code{describe}
+function that is useful for seeing all the slots of an object; it prints
+the slots and their values to standard output.
 
-@item
-@code{make} allocates memory for the new instance, and then invokes the
-@code{initialize} generic function to initialize the new instance's
-slots.
+@lisp
+(describe c)
+@print{}
+#<<my-complex> 401d8638> is an instance of class <my-complex>
+Slots are: 
+     r = 10
+     i = 3
+@end lisp
 
-@item
-The @code{initialize} generic function applies the method that is
-specialized for instances of type @code{<class>}, and this method
-performs the slot calculation.
-@end itemize
 
-In other words, rather than being hardcoded in @code{define-class}, the
-behaviour of class definition is encapsulated by generic function
-methods that are specialized for the class @code{<class>}.
+@node Slot Options
+@section Slot Options
 
-It is possible to create a new class that inherits from @code{<class>},
-which is called a ``metaclass'', and to write a new @code{initialize}
-method that is specialized for instances of the new metaclass.  Then, if
-the @code{define-class} form includes a @code{#:metaclass} class option
-whose value is the new metaclass, the class that is defined by the
-@code{define-class} form will be an instance of the new metaclass rather
-than of the default @code{<class>}, and will be defined in accordance
-with the new @code{initialize} method.  Thus the default slot
-calculation, as well as any other aspect of the new class's relationship
-with its superclasses, can be modified or overridden.
+When specifying a slot (in a @code{(define-class @dots{})} form),
+various options can be specified in addition to the slot's name.  Each
+option is specified by a keyword.  The list of possible keywords is
+as follows.
 
-In a similar way, the behaviour of generic functions can be modified or
-overridden by creating a new class that inherits from the standard
-generic function class @code{<generic>}, writing appropriate methods
-that are specialized to the new class, and creating new generic
-functions that are instances of the new class.
+@deffn {slot option} #:init-value init-value
+@deffnx {slot option} #:init-form init-form
+@deffnx {slot option} #:init-thunk init-thunk
+@deffnx {slot option} #:init-keyword init-keyword
+These options provide various ways to specify how to initialize the
+slot's value at instance creation time.
+@cindex default slot value
 
-The same is true for method metaobjects.  And the same basic mechanism
-allows the application class author to write an @code{initialize} method
-that is specialized to their application class, to initialize instances
-of that class.
+@var{init-value} specifies a fixed initial slot value (shared across all
+new instances of the class).
 
-Such is the power of the MOP.  Note that @code{initialize} is just one
-of a large number of generic functions that can be customized to modify
-the behaviour of application objects and classes and of GOOPS itself.
-Each subsequent section of the reference manual covers a particular area
-of GOOPS functionality, and describes the generic functions that are
-relevant for customization of that area.
-
-We conclude this subsubsection by emphasizing a point that may seem
-obvious, but contrasts with the corresponding situation in some other
-MOP implementations, such as CLOS.  The point is simply that an
-identifier which represents a GOOPS class or generic function is a
-variable with a first-class value, the value being an instance of class
-@code{<class>} or @code{<generic>}.  (In CLOS, on the other hand, a
-class identifier is a symbol that indexes the corresponding class
-metaobject in a separate namespace for classes.)  This is, of course,
-simply an extension of the tendency in Scheme to avoid the unnecessary
-use of, on the one hand, syntactic forms that require unevaluated
-arguments and, on the other, separate identifier namespaces (e.g. for
-class names), but it is worth noting that GOOPS conforms fully to this
-Schemely principle.
-
-@node Terminology
-@subsubsection Terminology
-
-It is assumed that the reader is already familiar with standard object
-orientation concepts such as classes, objects/instances,
-inheritance/subclassing, generic functions and methods, encapsulation
-and polymorphism.
-
-This section explains some of the less well known concepts and
-terminology that GOOPS uses, which are assumed by the following sections
-of the reference manual.
-
-@subsubheading Metaclass
+@var{init-thunk} specifies a thunk that will provide a default value for
+the slot.  The thunk is called when a new instance is created and should
+return the desired initial slot value.
 
-A @dfn{metaclass} is the class of an object which represents a GOOPS
-class.  Put more succinctly, a metaclass is a class's class.
+@var{init-form} specifies a form that, when evaluated, will return
+an initial value for the slot.  The form is evaluated each time that
+an instance of the class is created, in the lexical environment of the
+containing @code{define-class} expression.
 
-Most GOOPS classes have the metaclass @code{<class>} and, by default,
-any new class that is created using @code{define-class} has the
-metaclass @code{<class>}.
+@var{init-keyword} specifies a keyword that can be used to pass an
+initial slot value to @code{make} when creating a new instance.
 
-But what does this really mean?  To find out, let's look in more detail
-at what happens when a new class is created using @code{define-class}:
+Note that, since an @code{init-value} value is shared across all
+instances of a class, you should only use it when the initial value is
+an immutable value, like a constant.  If you want to initialize a slot
+with a fresh, independently mutable value, you should use
+@code{init-thunk} or @code{init-form} instead.  Consider the following
+example.
 
 @example
-(define-class <my-class> (<object>) . slots)
+(define-class <chbouib> ()
+  (hashtab #:init-value (make-hash-table)))
 @end example
 
-GOOPS actually expands the @code{define-class} form to something like
-this
+@noindent
+Here only one hash table is created and all instances of
+@code{<chbouib>} have their @code{hashtab} slot refer to it.  In order
+to have each instance of @code{<chbouib>} refer to a new hash table, you
+should instead write:
 
 @example
-(define <my-class> (class (<object>) . slots))
+(define-class <chbouib> ()
+  (hashtab #:init-thunk make-hash-table))
 @end example
 
-and thence to
+@noindent
+or:
 
 @example
-(define <my-class>
-  (make <class> #:supers (list <object>) #:slots slots))
+(define-class <chbouib> ()
+  (hashtab #:init-form (make-hash-table)))
 @end example
 
-In other words, the value of @code{<my-class>} is in fact an instance of
-the class @code{<class>} with slot values specifying the superclasses
-and slot definitions for the class @code{<my-class>}.  (@code{#:supers}
-and @code{#:slots} are initialization keywords for the @code{dsupers}
-and @code{dslots} slots of the @code{<class>} class.)
+If more than one of these options is specified for the same slot, the
+order of precedence, highest first is
+
+@itemize @bullet
+@item
+@code{#:init-keyword}, if @var{init-keyword} is present in the options
+passed to @code{make}
+
+@item
+@code{#:init-thunk}, @code{#:init-form} or @code{#:init-value}.
+@end itemize
+
+If the slot definition contains more than one initialization option of
+the same precedence, the later ones are ignored.  If a slot is not
+initialized at all, its value is unbound.
+
+In general, slots that are shared between more than one instance are
+only initialized at new instance creation time if the slot value is
+unbound at that time.  However, if the new instance creation specifies
+a valid init keyword and value for a shared slot, the slot is
+re-initialized regardless of its previous value.
 
-In order to take advantage of the full power of the GOOPS metaobject
-protocol (@pxref{MOP Specification}), it is sometimes desirable to
-create a new class with a metaclass other than the default
-@code{<class>}.  This is done by writing:
+Note, however, that the power of GOOPS' metaobject protocol means that
+everything written here may be customized or overridden for particular
+classes!  The slot initializations described here are performed by the least
+specialized method of the generic function @code{initialize}, whose
+signature is
 
 @example
-(define-class <my-class2> (<object>)
-   slot @dots{}
-   #:metaclass <my-metaclass>)
+(define-method (initialize (object <object>) initargs) ...)
 @end example
 
-GOOPS expands this to something like:
+The initialization of instances of any given class can be customized by
+defining a @code{initialize} method that is specialized for that class,
+and the author of the specialized method may decide to call
+@code{next-method} - which will result in a call to the next less
+specialized @code{initialize} method - at any point within the
+specialized code, or maybe not at all.  In general, therefore, the
+initialization mechanisms described here may be modified or overridden by
+more specialized code, or may not be supported at all for particular
+classes.
+@end deffn
+
+@deffn {slot option} #:getter getter
+@deffnx {slot option} #:setter setter
+@deffnx {slot option} #:accessor accessor
+Given an object @var{obj} with slots named @code{foo} and @code{bar}, it
+is always possible to read and write those slots by calling
+@code{slot-ref} and @code{slot-set!} with the relevant slot name; for
+example:
 
 @example
-(define <my-class2>
-  (make <my-metaclass> #:supers (list <object>) #:slots slots))
+(slot-ref @var{obj} 'foo)
+(slot-set! @var{obj} 'bar 25)
 @end example
 
-In this case, the value of @code{<my-class2>} is an instance of the more
-specialized class @code{<my-metaclass>}.  Note that
-@code{<my-metaclass>} itself must previously have been defined as a
-subclass of @code{<class>}.  For a full discussion of when and how it is
-useful to define new metaclasses, see @ref{MOP Specification}.
+The @code{#:getter}, @code{#:setter} and @code{#:accessor} options, if
+present, tell GOOPS to create generic function and method definitions
+that can be used to get and set the slot value more conveniently.
+@var{getter} specifies a generic function to which GOOPS will add a
+method for getting the slot value.  @var{setter} specifies a generic
+function to which GOOPS will add a method for setting the slot value.
+@var{accessor} specifies an accessor to which GOOPS will add methods for
+both getting and setting the slot value.
 
-Now let's make an instance of @code{<my-class2>}:
+So if a class includes a slot definition like this:
 
 @example
-(define my-object (make <my-class2> ...))
+(c #:getter get-count #:setter set-count #:accessor count)
 @end example
 
-All of the following statements are correct expressions of the
-relationships between @code{my-object}, @code{<my-class2>},
-@code{<my-metaclass>} and @code{<class>}.
-
-@itemize @bullet
-@item
-@code{my-object} is an instance of the class @code{<my-class2>}.
-
-@item
-@code{<my-class2>} is an instance of the class @code{<my-metaclass>}.
-
-@item
-@code{<my-metaclass>} is an instance of the class @code{<class>}.
-
-@item
-The class of @code{my-object} is @code{<my-class2>}.
-
-@item
-The metaclass of @code{my-object} is @code{<my-metaclass>}.
-
-@item
-The class of @code{<my-class2>} is @code{<my-metaclass>}.
-
-@item
-The metaclass of @code{<my-class2>} is @code{<class>}.
-
-@item
-The class of @code{<my-metaclass>} is @code{<class>}.
-
-@item
-The metaclass of @code{<my-metaclass>} is @code{<class>}.
-
-@item
-@code{<my-class2>} is not a metaclass, since it is does not inherit from
-@code{<class>}.
-
-@item
-@code{<my-metaclass>} is a metaclass, since it inherits from
-@code{<class>}.
-@end itemize
-
-@subsubheading Class Precedence List
-
-The @dfn{class precedence list} of a class is the list of all direct and
-indirect superclasses of that class, including the class itself.
-
-In the absence of multiple inheritance, the class precedence list is
-ordered straightforwardly, beginning with the class itself and ending
-with @code{<top>}.
-
-For example, given this inheritance hierarchy:
-
-@example
-(define-class <invertebrate> (<object>) @dots{})
-(define-class <echinoderm> (<invertebrate>) @dots{})
-(define-class <starfish> (<echinoderm>) @dots{})
-@end example
-
-the class precedence list of <starfish> would be
-
-@example
-(<starfish> <echinoderm> <invertebrate> <object> <top>)
-@end example
-
-With multiple inheritance, the algorithm is a little more complicated.
-A full description is provided by the GOOPS Tutorial: see @ref{Class
-precedence list}.
-
-``Class precedence list'' is often abbreviated, in documentation and
-Scheme variable names, to @dfn{cpl}.
-
-@subsubheading Accessor
-
-An @dfn{accessor} is a generic function with both reference and setter
-methods.
-
-@example
-(define-accessor perimeter)
-@end example
-
-Reference methods for an accessor are defined in the same way as generic
-function methods.
-
-@example
-(define-method (perimeter (s <square>))
-  (* 4 (side-length s)))
-@end example
-
-Setter methods for an accessor are defined by specifying ``(setter
-<accessor-name>)'' as the first parameter of the @code{define-method}
-call.
+GOOPS defines generic function methods such that the slot value can be
+referenced using either the getter or the accessor -
 
 @example
-(define-method ((setter perimeter) (s <square>) (n <number>))
-  (set! (side-length s) (/ n 4)))
+(let ((current-count (get-count obj))) @dots{})
+(let ((current-count (count obj))) @dots{})
 @end example
 
-Once an appropriate setter method has been defined in this way, it can
-be invoked using the generalized @code{set!} syntax, as in:
+- and set using either the setter or the accessor -
 
 @example
-(set! (perimeter s1) 18.3)
+(set-count obj (+ 1 current-count))
+(set! (count obj) (+ 1 current-count))
 @end example
 
-@node Defining New Classes
-@subsection Defining New Classes
-
-[ *fixme* Somewhere in this manual there needs to be an introductory
-discussion about GOOPS classes, generic functions and methods, covering
+Note that
 
 @itemize @bullet
 @item
-how classes encapsulate related items of data in @dfn{slots}
-
-@item
-why it is that, unlike in C++ and Java, a class does not encapsulate the
-methods that act upon the class (at least not in the C++/Java sense)
-
-@item
-how generic functions provide a more general solution that provides for
-dispatch on all argument types, and avoids idiosyncracies like C++'s
-friend classes
+with an accessor, the slot value is set using the generalized
+@code{set!} syntax
 
 @item
-how encapsulation in the sense of data- and code-hiding, or of
-distinguishing interface from implementation, is treated in Guile as an
-orthogonal concept to object orientation, and is the responsibility of
-the module system.
+in practice, it is unusual for a slot to use all three of these options:
+read-only, write-only and read-write slots would typically use only
+@code{#:getter}, @code{#:setter} and @code{#:accessor} options
+respectively.
 @end itemize
 
-Some of this is covered in the Tutorial chapter, in @ref{Generic
-functions and methods} - perhaps the best solution would be to expand
-the discussion there. ]
-
-@menu
-* Basic Class Definition::
-* Class Options::
-* Slot Options::
-* Class Definition Internals::
-* Customizing Class Definition::
-* STKlos Compatibility::
-@end menu
-
-@node Basic Class Definition
-@subsubsection Basic Class Definition
-
-New classes are defined using the @code{define-class} syntax, with
-arguments that specify the classes that the new class should inherit
-from, the direct slots of the new class, and any required class options.
-
-@deffn syntax define-class name (super @dots{}) slot-definition @dots{} . options
-Define a class called @var{name} that inherits from @var{super}s, with
-direct slots defined by @var{slot-definition}s and class options
-@var{options}.  The newly created class is bound to the variable name
-@var{name} in the current environment.
-
-Each @var{slot-definition} is either a symbol that names the slot or a
-list,
-
-@example
-(@var{slot-name-symbol} . @var{slot-options})
-@end example
-
-where @var{slot-name-symbol} is a symbol and @var{slot-options} is a
-list with an even number of elements.  The even-numbered elements of
-@var{slot-options} (counting from zero) are slot option keywords; the
-odd-numbered elements are the corresponding values for those keywords.
-
-@var{options} is a similarly structured list containing class option
-keywords and corresponding values.
-@end deffn
-
-The standard GOOPS class and slot options are described in the following
-subsubsections: see @ref{Class Options} and @ref{Slot Options}.
-
-Example 1.  Define a class that combines two pre-existing classes by
-inheritance but adds no new slots.
-
-@example
-(define-class <combined> (<tree> <bicycle>))
-@end example
-
-Example 2.  Define a @code{regular-polygon} class with slots for side
-length and number of sides that have default values and can be accessed
-via the generic functions @code{side-length} and @code{num-sides}.
-
-@example
-(define-class <regular-polygon> ()
-  (sl #:init-value 1 #:accessor side-length)
-  (ns #:init-value 5 #:accessor num-sides))
-@end example
-
-Example 3.  Define a class whose behavior (and that of its instances) is
-customized via an application-defined metaclass.
-
-@example
-(define-class <tcpip-fsm> ()
-  (s #:init-value #f #:accessor state)
-  ...
-  #:metaclass <finite-state-class>)
-@end example
-
-@node Class Options
-@subsubsection Class Options
-
-@deffn {class option} #:metaclass metaclass
-The @code{#:metaclass} class option specifies the metaclass of the class
-being defined.  @var{metaclass} must be a class that inherits from
-@code{<class>}.  For an introduction to the use of metaclasses, see
-@ref{Metaobjects and the Metaobject Protocol} and @ref{Terminology}.
-
-If the @code{#:metaclass} option is absent, GOOPS reuses or constructs a
-metaclass for the new class by calling @code{ensure-metaclass}
-(@pxref{Class Definition Internals,, ensure-metaclass}).
-@end deffn
-
-@deffn {class option} #:name name
-The @code{#:name} class option specifies the new class's name.  This
-name is used to identify the class whenever related objects - the class
-itself, its instances and its subclasses - are printed.
-
-If the @code{#:name} option is absent, GOOPS uses the first argument to
-@code{define-class} as the class name.
-@end deffn
-
-@deffn {class option} #:environment environment
-*fixme* Not sure about this one, but I think that the
-@code{#:environment} option specifies the environment in which the
-class's getters and setters are computed and evaluated.
-
-If the @code{#:environment} option is not specified, the class's
-environment defaults to the top-level environment in which the
-@code{define-class} form appears.
+The binding of the specified names is done in the environment of the
+@code{define-class} expression.  If the names are already bound (in that
+environment) to values that cannot be upgraded to generic functions,
+those values are overwritten when the @code{define-class} expression is
+evaluated.  For more detail, see @ref{Generic Function Internals,,
+ensure-generic}.
 @end deffn
 
-@node Slot Options
-@subsubsection Slot Options
-
 @deffn {slot option} #:allocation allocation
 The @code{#:allocation} option tells GOOPS how to allocate storage for
 the slot.  Possible values for @var{allocation} are
@@ -625,18 +416,24 @@ the slot.  Possible values for @var{allocation} are
 @itemize @bullet
 @item @code{#:instance}
 
+@findex #:instance
 Indicates that GOOPS should create separate storage for this slot in
-each new instance of the containing class (and its subclasses).
+each new instance of the containing class (and its subclasses).  This is
+the default.
 
 @item @code{#:class}
 
+@findex #:class
 Indicates that GOOPS should create storage for this slot that is shared
 by all instances of the containing class (and its subclasses).  In other
 words, a slot in class @var{C} with allocation @code{#:class} is shared
 by all @var{instance}s for which @code{(is-a? @var{instance} @var{c})}.
+This permits defining a kind of global variable which can be accessed
+only by (in)direct instances of the class which defines the slot.
 
 @item @code{#:each-subclass}
 
+@findex #:each-subclass
 Indicates that GOOPS should create storage for this slot that is shared
 by all @emph{direct} instances of the containing class, and that
 whenever a subclass of the containing class is defined, GOOPS should
@@ -647,14 +444,15 @@ instances of the subclass.  In other words, a slot with allocation
 
 @item @code{#:virtual}
 
+@findex #:slot-set!
+@findex #:slot-ref
+@findex #:virtual
 Indicates that GOOPS should not allocate storage for this slot.  The
 slot definition must also include the @code{#:slot-ref} and
 @code{#:slot-set!} options to specify how to reference and set the value
-for this slot.
+for this slot.  See the example below.
 @end itemize
 
-The default value is @code{#:instance}.
-
 Slot allocation options are processed when defining a new class by the
 generic function @code{compute-get-n-set}, which is specialized by the
 class's metaclass.  Hence new types of slot allocation can be
@@ -674,2118 +472,2465 @@ taking two parameters - @var{instance} and @var{new-val} - that sets the
 slot value to @var{new-val}.
 @end deffn
 
-@deffn {slot option} #:getter getter
-@deffnx {slot option} #:setter setter
-@deffnx {slot option} #:accessor accessor
-These options, if present, tell GOOPS to create generic function and
-method definitions that can be used to get and set the slot value more
-conveniently than by using @code{slot-ref} and @code{slot-set!}.
-
-@var{getter} specifies a generic function to which GOOPS will add a
-method for getting the slot value.  @var{setter} specifies a generic
-function to which GOOPS will add a method for setting the slot value.
-@var{accessor} specifies an accessor to which GOOPS will add methods for
-both getting and setting the slot value.
-
-So if a class includes a slot definition like this:
+@node Slot Description Example
+@section Illustrating Slot Description
 
-@example
-(c #:getter get-count #:setter set-count #:accessor count)
-@end example
+To illustrate slot description, we can redefine the @code{<my-complex>}
+class seen before. A definition could be:
 
-GOOPS defines generic function methods such that the slot value can be
-referenced using either the getter or the accessor -
+@lisp
+(define-class <my-complex> (<number>) 
+   (r #:init-value 0 #:getter get-r #:setter set-r! #:init-keyword #:r)
+   (i #:init-value 0 #:getter get-i #:setter set-i! #:init-keyword #:i))
+@end lisp
 
-@example
-(let ((current-count (get-count obj))) @dots{})
-(let ((current-count (count obj))) @dots{})
-@end example
+@noindent
+With this definition, the @code{r} and @code{i} slots are set to 0 by
+default, and can be initialised to other values by calling @code{make}
+with the @code{#:r} and @code{#:i} keywords.  Also the generic functions
+@code{get-r}, @code{set-r!}, @code{get-i} and @code{set-i!}  are
+automatically defined to read and write the slots.
 
-- and set using either the setter or the accessor -
+@lisp
+(define c1 (make <my-complex> #:r 1 #:i 2))
+(get-r c1) @result{} 1
+(set-r! c1 12)
+(get-r c1) @result{} 12
+(define c2 (make <my-complex> #:r 2))
+(get-r c2) @result{} 2
+(get-i c2) @result{} 0
+@end lisp
 
-@example
-(set-count obj (+ 1 current-count))
-(set! (count obj) (+ 1 current-count))
-@end example
+Accessors can both read and write a slot.  So, another definition of the
+@code{<my-complex>} class, using the @code{#:accessor} option, could be:
 
-Note that
+@findex set!
+@lisp
+(define-class <my-complex> (<number>) 
+   (r #:init-value 0 #:accessor real-part #:init-keyword #:r)
+   (i #:init-value 0 #:accessor imag-part #:init-keyword #:i))
+@end lisp
 
-@itemize @bullet
-@item
-with an accessor, the slot value is set using the generalized
-@code{set!} syntax
+@noindent
+With this definition, the @code{r} slot can be read with:
+@lisp
+(real-part c)
+@end lisp
+@noindent
+and set with:
+@lisp
+(set! (real-part c) new-value)
+@end lisp
 
-@item
-in practice, it is unusual for a slot to use all three of these options:
-read-only, write-only and read-write slots would typically use only
-@code{#:getter}, @code{#:setter} and @code{#:accessor} options
-respectively.
-@end itemize
+Suppose now that we want to manipulate complex numbers with both
+rectangular and polar coordinates.  One solution could be to have a
+definition of complex numbers which uses one particular representation
+and some conversion functions to pass from one representation to the
+other.  A better solution is to use virtual slots, like this:
 
-If the specified names are already bound in the top-level environment to
-values that cannot be upgraded to generic functions, those values are
-overwritten during evaluation of the @code{define-class} that contains
-the slot definition.  For details, see @ref{Generic Function Internals,,
-ensure-generic}.
-@end deffn
+@lisp
+(define-class <my-complex> (<number>)
+   ;; True slots use rectangular coordinates
+   (r #:init-value 0 #:accessor real-part #:init-keyword #:r)
+   (i #:init-value 0 #:accessor imag-part #:init-keyword #:i)
+   ;; Virtual slots access do the conversion
+   (m #:accessor magnitude #:init-keyword #:magn  
+      #:allocation #:virtual
+      #:slot-ref (lambda (o)
+                  (let ((r (slot-ref o 'r)) (i (slot-ref o 'i)))
+                    (sqrt (+ (* r r) (* i i)))))
+      #:slot-set! (lambda (o m)
+                    (let ((a (slot-ref o 'a)))
+                      (slot-set! o 'r (* m (cos a)))
+                      (slot-set! o 'i (* m (sin a))))))
+   (a #:accessor angle #:init-keyword #:angle
+      #:allocation #:virtual
+      #:slot-ref (lambda (o)
+                  (atan (slot-ref o 'i) (slot-ref o 'r)))
+      #:slot-set! (lambda(o a)
+                   (let ((m (slot-ref o 'm)))
+                      (slot-set! o 'r (* m (cos a)))
+                      (slot-set! o 'i (* m (sin a)))))))
 
-@deffn {slot option} #:init-value init-value
-@deffnx {slot option} #:init-form init-form
-@deffnx {slot option} #:init-thunk init-thunk
-@deffnx {slot option} #:init-keyword init-keyword
-These options provide various ways to specify how to initialize the
-slot's value at instance creation time.  @var{init-value} is a fixed
-value (shared across all new instances of the class).
-@var{init-thunk} is a procedure of no arguments that is called
-when a new instance is created and should return the desired initial
-slot value.  @var{init-form} is an unevaluated expression that gets
-evaluated when a new instance is created and should return the desired
-initial slot value.  @var{init-keyword} is a keyword that can be used
-to pass an initial slot value to @code{make} when creating a new
-instance.
+@end lisp
 
-Note that, since an @code{init-value} value is shared across all
-instances of a class, you should only use it when the initial value is
-an immutable value, like a constant.  If you want to initialize a slot
-with a fresh, independently mutable value, you should use
-@code{init-thunk} or @code{init-form} instead.  Consider the following
-example.
+In this class definition, the magnitude @code{m} and angle @code{a}
+slots are virtual, and are calculated, when referenced, from the normal
+(i.e.@: @code{#:allocation #:instance}) slots @code{r} and @code{i}, by
+calling the function defined in the relevant @code{#:slot-ref} option.
+Correspondingly, writing @code{m} or @code{a} leads to calling the
+function defined in the @code{#:slot-set!} option.  Thus the
+following expression
 
-@example
-(define-class <chbouib> ()
-  (hashtab #:init-value (make-hash-table)))
-@end example
+@findex #:slot-set!
+@findex #:slot-ref
+@lisp
+(slot-set! c 'a 3)
+@end lisp
 
 @noindent
-Here only one hash table is created and all instances of
-@code{<chbouib>} have their @code{hashtab} slot refer to it.  In order
-to have each instance of @code{<chbouib>} refer to a new hash table, you
-should instead write:
+permits to set the angle of the @code{c} complex number.
 
-@example
-(define-class <chbouib> ()
-  (hashtab #:init-thunk make-hash-table))
-@end example
+@lisp
+(define c (make <my-complex> #:r 12 #:i 20))
+(real-part c) @result{} 12
+(angle c) @result{} 1.03037682652431
+(slot-set! c 'i 10)
+(set! (real-part c) 1)
+(describe c)
+@print{}
+#<<my-complex> 401e9b58> is an instance of class <my-complex>
+Slots are: 
+     r = 1
+     i = 10
+     m = 10.0498756211209
+     a = 1.47112767430373
+@end lisp
 
-@noindent
-or:
+Since initialization keywords have been defined for the four slots, we
+can now define the standard Scheme primitives @code{make-rectangular}
+and @code{make-polar}.
 
-@example
-(define-class <chbouib> ()
-  (hashtab #:init-form (make-hash-table)))
-@end example
+@lisp
+(define make-rectangular 
+   (lambda (x y) (make <my-complex> #:r x #:i y)))
 
-If more than one of these options is specified for the same slot, the
-order of precedence, highest first is
+(define make-polar
+   (lambda (x y) (make <my-complex> #:magn x #:angle y)))
+@end lisp
 
-@itemize @bullet
-@item
-@code{#:init-keyword}, if @var{init-keyword} is present in the options
-passed to @code{make}
 
-@item
-@code{#:init-thunk}, @code{#:init-form} or @code{#:init-value}.
-@end itemize
+@node Methods and Generic Functions
+@section Methods and Generic Functions
 
-If the slot definition contains more than one initialization option of
-the same precedence, the later ones are ignored.  If a slot is not
-initialized at all, its value is unbound.
+A GOOPS method is like a Scheme procedure except that it is specialized
+for a particular set of argument classes, and will only be used when the
+actual arguments in a call match the classes in the method definition.
 
-In general, slots that are shared between more than one instance are
-only initialized at new instance creation time if the slot value is
-unbound at that time.  However, if the new instance creation specifies
-a valid init keyword and value for a shared slot, the slot is
-re-initialized regardless of its previous value.
+@lisp
+(define-method (+ (x <string>) (y <string>))
+  (string-append x y))
 
-Note, however, that the power of GOOPS' metaobject protocol means that
-everything written here may be customized or overridden for particular
-classes!  The slot initializations described here are performed by the least
-specialized method of the generic function @code{initialize}, whose
-signature is
+(+ "abc" "de") @result{} "abcde"
+@end lisp
 
-@example
-(define-method (initialize (object <object>) initargs) ...)
-@end example
+A method is not formally associated with any single class (as it is in
+many other object oriented languages), because a method can be
+specialized for a combination of several classes.  If you've studied
+object orientation in non-Lispy languages, you may remember discussions
+such as whether a method to stretch a graphical image around a surface
+should be a method of the image class, with a surface as a parameter, or
+a method of the surface class, with an image as a parameter.  In GOOPS
+you'd just write
 
-The initialization of instances of any given class can be customized by
-defining a @code{initialize} method that is specialized for that class,
-and the author of the specialized method may decide to call
-@code{next-method} - which will result in a call to the next less
-specialized @code{initialize} method - at any point within the
-specialized code, or maybe not at all.  In general, therefore, the
-initialization mechanisms described here may be modified or overridden by
-more specialized code, or may not be supported at all for particular
-classes.
-@end deffn
-
-@node Class Definition Internals
-@subsubsection Class Definition Internals
-
-Implementation notes: @code{define-class} expands to an expression which
+@lisp
+(define-method (stretch (im <image>) (sf <surface>))
+  ...)
+@end lisp
 
-@itemize @bullet
-@item
-checks that it is being evaluated only at top level
+@noindent
+and the question of which class the method is more associated with does
+not need answering.
 
-@item
-defines any accessors that are implied by the @var{slot-definition}s
+There can simultaneously be several methods with the same name but
+different sets of specializing argument classes; for example:
 
-@item
-uses @code{class} to create the new class (@pxref{Class Definition
-Internals,, class})
+@lisp
+(define-method (+ (x <string>) (y <string)) ...)
+(define-method (+ (x <matrix>) (y <matrix>)) ...)
+(define-method (+ (f <fish>) (b <bicycle>)) ...)
+(define-method (+ (a <foo>) (b <bar>) (c <baz>)) ...)
+@end lisp
 
-@item
-checks for a previous class definition for @var{name} and, if found,
-handles the redefinition by invoking @code{class-redefinition}
-(@pxref{Redefining a Class}).
-@end itemize
+@noindent
+A generic function is a container for the set of such methods that a
+program intends to use.
+
+If you look at a program's source code, and see @code{(+ x y)} somewhere
+in it, conceptually what is happening is that the program at that point
+calls a generic function (in this case, the generic function bound to
+the identifier @code{+}).  When that happens, Guile works out which of
+the generic function's methods is the most appropriate for the arguments
+that the function is being called with; then it evaluates the method's
+code with the arguments as formal parameters.  This happens every time
+that a generic function call is evaluated --- it isn't assumed that a
+given source code call will end up invoking the same method every time.
+
+Defining an identifier as a generic function is done with the
+@code{define-generic} macro.  Definition of a new method is done with
+the @code{define-method} macro.  Note that @code{define-method}
+automatically does a @code{define-generic} if the identifier concerned
+is not already a generic function, so often an explicit
+@code{define-generic} call is not needed.
+@findex define-generic
+@findex define-method
 
-@deffn syntax class name (super @dots{}) slot-definition @dots{} . options
-Return a newly created class that inherits from @var{super}s, with
-direct slots defined by @var{slot-definition}s and class options
-@var{options}.  For the format of @var{slot-definition}s and
-@var{options}, see @ref{Basic Class Definition,, define-class}.
+@deffn syntax define-generic symbol
+Create a generic function with name @var{symbol} and bind it to the
+variable @var{symbol}.  If @var{symbol} was previously bound to a Scheme
+procedure (or procedure-with-setter), the old procedure (and setter) is
+incorporated into the new generic function as its default procedure (and
+setter).  Any other previous value, including an existing generic
+function, is discarded and replaced by a new, empty generic function.
 @end deffn
 
-Implementation notes: @code{class} expands to an expression which
+@deffn syntax define-method (generic parameter @dots{}) body @dots{}
+Define a method for the generic function or accessor @var{generic} with
+parameters @var{parameter}s and body @var{body} @enddots{}.
 
-@itemize @bullet
-@item
-processes the class and slot definition options to check that they are
-well-formed, to convert the @code{#:init-form} option to an
-@code{#:init-thunk} option, to supply a default environment parameter
-(the current top-level environment) and to evaluate all the bits that
-need to be evaluated
+@var{generic} is a generic function.  If @var{generic} is a variable
+which is not yet bound to a generic function object, the expansion of
+@code{define-method} will include a call to @code{define-generic}.  If
+@var{generic} is @code{(setter @var{generic-with-setter})}, where
+@var{generic-with-setter} is a variable which is not yet bound to a
+generic-with-setter object, the expansion will include a call to
+@code{define-accessor}.
 
-@item
-calls @code{make-class} to create the class with the processed and
-evaluated parameters.
-@end itemize
+Each @var{parameter} must be either a symbol or a two-element list
+@code{(@var{symbol} @var{class})}.  The symbols refer to variables in
+the body forms that will be bound to the parameters supplied by the
+caller when calling this method.  The @var{class}es, if present,
+specify the possible combinations of parameters to which this method
+can be applied.
 
-@deffn procedure make-class supers slots . options
-Return a newly created class that inherits from @var{supers}, with
-direct slots defined by @var{slots} and class options @var{options}.
-For the format of @var{slots} and @var{options}, see @ref{Basic Class
-Definition,, define-class}, except note that for @code{make-class},
-@var{slots} and @var{options} are separate list parameters: @var{slots}
-here is a list of slot definitions.
+@var{body} @dots{} are the bodies of the method definition.
 @end deffn
 
-Implementation notes: @code{make-class}
+@code{define-method} expressions look a little like Scheme procedure
+definitions of the form
 
-@itemize @bullet
-@item
-adds @code{<object>} to the @var{supers} list if @var{supers} is empty
-or if none of the classes in @var{supers} have @code{<object>} in their
-class precedence list
+@example
+(define (name formals @dots{}) . body)
+@end example
 
-@item
-defaults the @code{#:environment}, @code{#:name} and @code{#:metaclass}
-options, if they are not specified by @var{options}, to the current
-top-level environment, the unbound value, and @code{(ensure-metaclass
-@var{supers})} respectively (@pxref{Class Definition Internals,,
-ensure-metaclass})
+The important difference is that each formal parameter, apart from the
+possible ``rest'' argument, can be qualified by a class name:
+@code{@var{formal}} becomes @code{(@var{formal} @var{class})}.  The
+meaning of this qualification is that the method being defined
+will only be applicable in a particular generic function invocation if
+the corresponding argument is an instance of @code{@var{class}} (or one of
+its subclasses).  If more than one of the formal parameters is qualified
+in this way, then the method will only be applicable if each of the
+corresponding arguments is an instance of its respective qualifying class.
 
-@item
-checks for duplicate classes in @var{supers} and duplicate slot names in
-@var{slots}, and signals an error if there are any duplicates
+Note that unqualified formal parameters act as though they are qualified
+by the class @code{<top>}, which GOOPS uses to mean the superclass of
+all valid Scheme types, including both primitive types and GOOPS classes.
 
-@item
-calls @code{make}, passing the metaclass as the first parameter and all
-other parameters as option keywords with values.
-@end itemize
+For example, if a generic function method is defined with
+@var{parameter}s @code{(s1 <square>)} and @code{(n <number>)}, that
+method is only applicable to invocations of its generic function that
+have two parameters where the first parameter is an instance of the
+@code{<square>} class and the second parameter is a number.
 
-@deffn procedure ensure-metaclass supers env
-Return a metaclass suitable for a class that inherits from the list of
-classes in @var{supers}.  The returned metaclass is the union by
-inheritance of the metaclasses of the classes in @var{supers}.
+@menu
+* Accessors::
+* Extending Primitives::
+* Merging Generics::
+* Next-method::                 
+* Generic Function and Method Examples::                     
+* Handling Invocation Errors::
+@end menu
 
-In the simplest case, where all the @var{supers} are straightforward
-classes with metaclass @code{<class>}, the returned metaclass is just
-@code{<class>}.
 
-For a more complex example, suppose that @var{supers} contained one
-class with metaclass @code{<operator-class>} and one with metaclass
-@code{<foreign-object-class>}.  Then the returned metaclass would be a
-class that inherits from both @code{<operator-class>} and
-@code{<foreign-object-class>}.
+@node Accessors
+@subsection Accessors
 
-If @var{supers} is the empty list, @code{ensure-metaclass} returns the
-default GOOPS metaclass @code{<class>}.
+An accessor is a generic function that can also be used with the
+generalized @code{set!} syntax (@pxref{Procedures with Setters}).  Guile
+will handle a call like
 
-GOOPS keeps a list of the metaclasses created by
-@code{ensure-metaclass}, so that each required type of metaclass only
-has to be created once.
+@example
+(set! (@code{accessor} @code{args}@dots{}) @code{value})
+@end example
 
-The @code{env} parameter is ignored.
-@end deffn
+@noindent
+by calling the most specialized method of @code{accessor} that matches
+the classes of @code{args} and @code{value}.  @code{define-accessor} is
+used to bind an identifier to an accessor.
 
-@deffn procedure ensure-metaclass-with-supers meta-supers
-@code{ensure-metaclass-with-supers} is an internal procedure used by
-@code{ensure-metaclass} (@pxref{Class Definition Internals,,
-ensure-metaclass}).  It returns a metaclass that is the union by
-inheritance of the metaclasses in @var{meta-supers}.
+@deffn syntax define-accessor symbol
+Create an accessor with name @var{symbol} and bind it to the variable
+@var{symbol}.  If @var{symbol} was previously bound to a Scheme
+procedure (or procedure-with-setter), the old procedure (and setter) is
+incorporated into the new accessor as its default procedure (and
+setter).  Any other previous value, including an existing generic
+function or accessor, is discarded and replaced by a new, empty
+accessor.
 @end deffn
 
-The internals of @code{make}, which is ultimately used to create the new
-class object, are described in @ref{Customizing Instance Creation},
-which covers the creation and initialization of instances in general.
 
-@node Customizing Class Definition
-@subsubsection Customizing Class Definition
+@node Extending Primitives
+@subsection Extending Primitives
 
-During the initialization of a new class, GOOPS calls a number of generic
-functions with the newly allocated class instance as the first
-argument.  Specifically, GOOPS calls the generic function
+Many of Guile's primitive procedures can be extended by giving them a
+generic function definition that operates in conjunction with their
+normal C-coded implementation.  When a primitive is extended in this
+way, it behaves like a generic function with the C-coded implementation
+as its default method.
 
-@itemize @bullet
-@item
-(initialize @var{class} @dots{})
-@end itemize
+This extension happens automatically if a method is defined (by a
+@code{define-method} call) for a variable whose current value is a
+primitive.  But it can also be forced by calling
+@code{enable-primitive-generic!}.
 
-where @var{class} is the newly allocated class instance, and the default
-@code{initialize} method for arguments of type @code{<class>} calls the
-generic functions
+@deffn {primitive procedure} enable-primitive-generic! primitive
+Force the creation of a generic function definition for
+@var{primitive}.
+@end deffn
 
-@itemize @bullet
-@item
-(compute-cpl @var{class})
+Once the generic function definition for a primitive has been created,
+it can be retrieved using @code{primitive-generic-generic}.
 
-@item
-(compute-slots @var{class})
+@deffn {primitive procedure} primitive-generic-generic primitive
+Return the generic function definition of @var{primitive}.
 
-@item
-(compute-get-n-set @var{class} @var{slot-def}), for each of the slot
-definitions returned by @code{compute-slots}
+@code{primitive-generic-generic} raises an error if @var{primitive}
+is not a primitive with generic capability.
+@end deffn
 
-@item
-(compute-getter-method @var{class} @var{slot-def}), for each of the
-slot definitions returned by @code{compute-slots} that includes a
-@code{#:getter} or @code{#:accessor} slot option
+@node Merging Generics
+@subsection Merging Generics
 
-@item
-(compute-setter-method @var{class} @var{slot-def}), for each of the
-slot definitions returned by @code{compute-slots} that includes a
-@code{#:setter} or @code{#:accessor} slot option.
-@end itemize
+GOOPS generic functions and accessors often have short, generic names.
+For example, if a vector package provides an accessor for the X
+coordinate of a vector, that accessor may just be called @code{x}.  It
+doesn't need to be called, for example, @code{vector:x}, because
+GOOPS will work out, when it sees code like @code{(x @var{obj})}, that
+the vector-specific method of @code{x} should be called if @var{obj} is
+a vector.
 
-If the metaclass of the new class is something more specialized than the
-default @code{<class>}, then the type of @var{class} in the calls above
-is more specialized than @code{<class>}, and hence it becomes possible
-to define generic function methods, specialized for the new class's
-metaclass, that can modify or override the default behaviour of
-@code{initialize}, @code{compute-cpl} or @code{compute-get-n-set}.
+That raises the question, though, of what happens when different
+packages define a generic function with the same name.  Suppose we work
+with a graphical package which needs to use two independent vector
+packages for 2D and 3D vectors respectively.  If both packages export
+@code{x}, what does the code using those packages end up with?
 
-@code{compute-cpl} computes the class precedence list (``CPL'') for the
-new class (@pxref{Class precedence list}), and returns it as a list of
-class objects.  The CPL is important because it defines a superclass
-ordering that is used, when a generic function is invoked upon an
-instance of the class, to decide which of the available generic function
-methods is the most specific.  Hence @code{compute-cpl} could be
-customized in order to modify the CPL ordering algorithm for all classes
-with a special metaclass.
+@ref{Creating Guile Modules,,duplicate binding handlers} explains how
+this is resolved for conflicting bindings in general.  For generics,
+there is a special duplicates handler, @code{merge-generics}, which
+tells the module system to merge generic functions with the same name.
+Here is an example:
 
-The default CPL algorithm is encapsulated by the @code{compute-std-cpl}
-procedure, which is in turn called by the default @code{compute-cpl}
-method.
+@lisp
+(define-module (math 2D-vectors)
+  #:use-module (oop goops)
+  #:export (x y ...))
+                 
+(define-module (math 3D-vectors)
+  #:use-module (oop goops)
+  #:export (x y z ...))
 
-@deffn procedure compute-std-cpl class
-Compute and return the class precedence list for @var{class} according
-to the algorithm described in @ref{Class precedence list}.
-@end deffn
+(define-module (my-module)
+  #:use-module (oop goops)
+  #:use-module (math 2D-vectors)
+  #:use-module (math 3D-vectors)
+  #:duplicates (merge-generics))
+@end lisp
 
-@code{compute-slots} computes and returns a list of all slot definitions
-for the new class.  By default, this list includes the direct slot
-definitions from the @code{define-class} form, plus the slot definitions
-that are inherited from the new class's superclasses.  The default
-@code{compute-slots} method uses the CPL computed by @code{compute-cpl}
-to calculate this union of slot definitions, with the rule that slots
-inherited from superclasses are shadowed by direct slots with the same
-name.  One possible reason for customizing @code{compute-slots} would be
-to implement an alternative resolution strategy for slot name conflicts.
+The generic function @code{x} in @code{(my-module)} will now incorporate
+all of the methods of @code{x} from both imported modules.
+
+To be precise, there will now be three distinct generic functions named
+@code{x}: @code{x} in @code{(math 2D-vectors)}, @code{x} in @code{(math
+3D-vectors)}, and @code{x} in @code{(my-module)}; and these functions
+share their methods in an interesting and dynamic way.
+
+To explain, let's call the imported generic functions (in @code{(math
+2D-vectors)} and @code{(math 3D-vectors)}) the @dfn{ancestors}, and the
+merged generic function (in @code{(my-module)}), the @dfn{descendant}.
+The general rule is that for any generic function G, the applicable
+methods are selected from the union of the methods of G's descendant
+functions, the methods of G itself and the methods of G's ancestor
+functions.
+
+Thus ancestor functions effectively share methods with their
+descendants, and vice versa.  In the example above, @code{x} in
+@code{(math 2D-vectors)} will share the methods of @code{x} in
+@code{(my-module)} and vice versa.@footnote{But note that @code{x} in
+@code{(math 2D-vectors)} doesn't share methods with @code{x} in
+@code{(math 3D-vectors)}, so modularity is still preserved.}  Sharing is
+dynamic, so adding another new method to a descendant implies adding it
+to that descendant's ancestors too.
+
+@node Next-method
+@subsection Next-method
+
+When you call a generic function, with a particular set of arguments,
+GOOPS builds a list of all the methods that are applicable to those
+arguments and orders them by how closely the method definitions match
+the actual argument types.  It then calls the method at the top of this
+list.  If the selected method's code wants to call on to the next method
+in this list, it can do so by using @code{next-method}.
 
-@code{compute-get-n-set} computes the low-level closures that will be
-used to get and set the value of a particular slot, and returns them in
-a list with two elements.
+@lisp
+(define-method (Test (a <integer>)) (cons 'integer (next-method)))
+(define-method (Test (a <number>))  (cons 'number  (next-method)))
+(define-method (Test a)             (list 'top))
+@end lisp
 
-The closures returned depend on how storage for that slot is allocated.
-The standard @code{compute-get-n-set} method, specialized for classes of
-type @code{<class>}, handles the standard GOOPS values for the
-@code{#:allocation} slot option (@pxref{Slot Options,, allocation}).  By
-defining a new @code{compute-get-n-set} method for a more specialized
-metaclass, it is possible to support new types of slot allocation.
+With these definitions,
 
-Suppose you wanted to create a large number of instances of some class
-with a slot that should be shared between some but not all instances of
-that class - say every 10 instances should share the same slot storage.
-The following example shows how to implement and use a new type of slot
-allocation to do this.
+@lisp
+(Test 1)   @result{} (integer number top)
+(Test 1.0) @result{} (number top)
+(Test #t)  @result{} (top)
+@end lisp
 
-@example
-(define-class <batched-allocation-metaclass> (<class>))
+@code{next-method} is always called as just @code{(next-method)}.  The
+arguments for the next method call are always implicit, and always the
+same as for the original method call.
 
-(let ((batch-allocation-count 0)
-      (batch-get-n-set #f))
-  (define-method (compute-get-n-set
-                     (class <batched-allocation-metaclass>) s)
-    (case (slot-definition-allocation s)
-      ((#:batched)
-       ;; If we've already used the same slot storage for 10 instances,
-       ;; reset variables.
-       (if (= batch-allocation-count 10)
-           (begin
-             (set! batch-allocation-count 0)
-             (set! batch-get-n-set #f)))
-       ;; If we don't have a current pair of get and set closures,
-       ;; create one.  make-closure-variable returns a pair of closures
-       ;; around a single Scheme variable - see goops.scm for details.
-       (or batch-get-n-set
-           (set! batch-get-n-set (make-closure-variable)))
-       ;; Increment the batch allocation count.
-       (set! batch-allocation-count (+ batch-allocation-count 1))
-       batch-get-n-set)
+If you want to call on to a method with the same name but with a
+different set of arguments (as you might with overloaded methods in C++,
+for example), you do not use @code{next-method}, but instead simply
+write the new call as usual:
 
-      ;; Call next-method to handle standard allocation types.
-      (else (next-method)))))
+@lisp
+(define-method (Test (a <number>) min max)
+  (if (and (>= a min) (<= a max))
+      (display "Number is in range\n"))
+  (Test a))
+
+(Test 2 1 10)
+@print{}
+Number is in range
+@result{}
+(integer number top)
+@end lisp
 
-(define-class <class-using-batched-slot> ()
-  ...
-  (c #:allocation #:batched)
-  ...
-  #:metaclass <batched-allocation-metaclass>)
-@end example
+(You should be careful in this case that the @code{Test} calls do not
+lead to an infinite recursion, but this consideration is just the same
+as in Scheme code in general.)
 
-The usage of @code{compute-getter-method} and @code{compute-setter-method}
-is described in @ref{MOP Specification}.
+@node Generic Function and Method Examples
+@subsection Generic Function and Method Examples
 
-@code{compute-cpl} and @code{compute-get-n-set} are called by the
-standard @code{initialize} method for classes whose metaclass is
-@code{<class>}.  But @code{initialize} itself can also be modified, by
-defining an @code{initialize} method specialized to the new class's
-metaclass.  Such a method could complete override the standard
-behaviour, by not calling @code{(next-method)} at all, but more
-typically it would perform additional class initialization steps before
-and/or after calling @code{(next-method)} for the standard behaviour.
+Consider the following definitions:
 
-@node STKlos Compatibility
-@subsubsection STKlos Compatibility
+@lisp
+(define-generic G)
+(define-method (G (a <integer>) b) 'integer)
+(define-method (G (a <real>) b) 'real)
+(define-method (G a b) 'top)
+@end lisp
 
-If the STKlos compatibility module is loaded, @code{define-class} is
-overwritten by a STKlos-specific definition; the standard GOOPS
-definition of @code{define-class} remains available in
-@code{standard-define-class}.
+The @code{define-generic} call defines @var{G} as a generic function.
+The three next lines define methods for @var{G}.  Each method uses a
+sequence of @dfn{parameter specializers} that specify when the given
+method is applicable.  A specializer permits to indicate the class a
+parameter must belong to (directly or indirectly) to be applicable.  If
+no specializer is given, the system defaults it to @code{<top>}.  Thus,
+the first method definition is equivalent to
 
-@deffn syntax standard-define-class name (super @dots{}) slot-definition @dots{} . options
-@code{standard-define-class} is equivalent to the standard GOOPS
-@code{define-class}.
-@end deffn
+@cindex parameter specializers
+@lisp
+(define-method (G (a <integer>) (b <top>)) 'integer)
+@end lisp
 
-@node Creating Instances
-@subsection Creating Instances
+Now, let's look at some possible calls to the generic function @var{G}:
 
-@menu
-* Basic Instance Creation::
-* Customizing Instance Creation::
-@end menu
+@lisp
+(G 2 3)    @result{} integer
+(G 2 #t)   @result{} integer
+(G 1.2 'a) @result{} real
+@c (G #3 'a) @result{} real       @c was {\sharpsign}
+(G #t #f)  @result{} top
+(G 1 2 3)  @result{} error (since no method exists for 3 parameters)
+@end lisp
 
-@node Basic Instance Creation
-@subsubsection Basic Instance Creation
+The methods above use only one specializer per parameter list.  But in
+general, any or all of a method's parameters may be specialized.
+Suppose we define now:
 
-To create a new instance of any GOOPS class, use the generic function
-@code{make} or @code{make-instance}, passing the required class and any
-appropriate instance initialization arguments as keyword and value
-pairs.  Note that @code{make} and @code{make-instances} are aliases for
-each other - their behaviour is identical.
+@lisp
+(define-method (G (a <integer>) (b <number>))  'integer-number)
+(define-method (G (a <integer>) (b <real>))    'integer-real)
+(define-method (G (a <integer>) (b <integer>)) 'integer-integer)
+(define-method (G a (b <number>))              'top-number)
+@end lisp
 
-@deffn generic make
-@deffnx method make (class <class>) . initargs
-Create and return a new instance of class @var{class}, initialized using
-@var{initargs}.
+@noindent With these definitions:
 
-In theory, @var{initargs} can have any structure that is understood by
-whatever methods get applied when the @code{initialize} generic function
-is applied to the newly allocated instance.
+@lisp
+(G 1 2)   @result{} integer-integer
+(G 1 1.0) @result{} integer-real
+(G 1 #t)  @result{} integer
+(G 'a 1)  @result{} top-number
+@end lisp
 
-In practice, specialized @code{initialize} methods would normally call
-@code{(next-method)}, and so eventually the standard GOOPS
-@code{initialize} methods are applied.  These methods expect
-@var{initargs} to be a list with an even number of elements, where
-even-numbered elements (counting from zero) are keywords and
-odd-numbered elements are the corresponding values.
+As a further example we shall continue to define operations on the
+@code{<my-complex>} class.  Suppose that we want to use it to implement
+complex numbers completely.  For instance a definition for the addition
+of two complex numbers could be
 
-GOOPS processes initialization argument keywords automatically for slots
-whose definition includes the @code{#:init-keyword} option (@pxref{Slot
-Options,, init-keyword}).  Other keyword value pairs can only be
-processed by an @code{initialize} method that is specialized for the new
-instance's class.  Any unprocessed keyword value pairs are ignored.
-@end deffn
-
-@deffn generic make-instance
-@deffnx method make-instance (class <class>) . initargs
-@code{make-instance} is an alias for @code{make}.
-@end deffn
+@lisp
+(define-method (new-+ (a <my-complex>) (b <my-complex>))
+  (make-rectangular (+ (real-part a) (real-part b))
+                    (+ (imag-part a) (imag-part b))))
+@end lisp
 
-@node Customizing Instance Creation
-@subsubsection Customizing Instance Creation
+To be sure that the @code{+} used in the method @code{new-+} is the
+standard addition we can do:
 
-@code{make} itself is a generic function.  Hence the @code{make}
-invocation itself can be customized in the case where the new instance's
-metaclass is more specialized than the default @code{<class>}, by
-defining a @code{make} method that is specialized to that metaclass.
+@lisp
+(define-generic new-+)
 
-Normally, however, the method for classes with metaclass @code{<class>}
-will be applied.  This method calls two generic functions:
+(let ((+ +))
+  (define-method (new-+ (a <my-complex>) (b <my-complex>))
+    (make-rectangular (+ (real-part a) (real-part b))
+                      (+ (imag-part a) (imag-part b)))))
+@end lisp
 
-@itemize @bullet
-@item
-(allocate-instance @var{class} . @var{initargs})
+The @code{define-generic} ensures here that @code{new-+} will be defined
+in the global environment. Once this is done, we can add methods to the
+generic function @code{new-+} which make a closure on the @code{+}
+symbol.  A complete writing of the @code{new-+} methods is shown in
+@ref{fig:newplus}.
 
-@item
-(initialize @var{instance} . @var{initargs})
-@end itemize
+@float Figure,fig:newplus
+@lisp
+(define-generic new-+)
 
-@code{allocate-instance} allocates storage for and returns the new
-instance, uninitialized.  You might customize @code{allocate-instance},
-for example, if you wanted to provide a GOOPS wrapper around some other
-object programming system.
+(let ((+ +))
 
-To do this, you would create a specialized metaclass, which would act as
-the metaclass for all classes and instances from the other system.  Then
-define an @code{allocate-instance} method, specialized to that
-metaclass, which calls a Guile primitive C function, which in turn
-allocates the new instance using the interface of the other object
-system.
+  (define-method (new-+ (a <real>) (b <real>)) (+ a b))
 
-In this case, for a complete system, you would also need to customize a
-number of other generic functions like @code{make} and
-@code{initialize}, so that GOOPS knows how to make classes from the
-other system, access instance slots, and so on.
+  (define-method (new-+ (a <real>) (b <my-complex>)) 
+    (make-rectangular (+ a (real-part b)) (imag-part b)))
 
-@code{initialize} initializes the instance that is returned by
-@code{allocate-instance}.  The standard GOOPS methods perform
-initializations appropriate to the instance class.
+  (define-method (new-+ (a <my-complex>) (b <real>))
+    (make-rectangular (+ (real-part a) b) (imag-part a)))
 
-@itemize @bullet
-@item
-At the least specialized level, the method for instances of type
-@code{<object>} performs internal GOOPS instance initialization, and
-initializes the instance's slots according to the slot definitions and
-any slot initialization keywords that appear in @var{initargs}.
+  (define-method (new-+ (a <my-complex>) (b <my-complex>))
+    (make-rectangular (+ (real-part a) (real-part b))
+                      (+ (imag-part a) (imag-part b))))
 
-@item
-The method for instances of type @code{<class>} calls
-@code{(next-method)}, then performs the class initializations described
-in @ref{Customizing Class Definition}.
+  (define-method (new-+ (a <number>))  a)
+  
+  (define-method (new-+) 0)
 
-@item
-and so on for generic functions, method, operator classes @dots{}
-@end itemize
+  (define-method (new-+ . args)
+    (new-+ (car args) 
+      (apply new-+ (cdr args)))))
 
-Similarly, you can customize the initialization of instances of any
-application-defined class by defining an @code{initialize} method
-specialized to that class.
+(set! + new-+)
+@end lisp
 
-Imagine a class whose instances' slots need to be initialized at
-instance creation time by querying a database.  Although it might be
-possible to achieve this a combination of @code{#:init-thunk} keywords
-and closures in the slot definitions, it is neater to write an
-@code{initialize} method for the class that queries the database once
-and initializes all the dependent slot values according to the results.
+@caption{Extending @code{+} to handle complex numbers}
+@end float
+
+We take advantage here of the fact that generic function are not obliged
+to have a fixed number of parameters.  The four first methods implement
+dyadic addition.  The fifth method says that the addition of a single
+element is this element itself.  The sixth method says that using the
+addition with no parameter always return 0 (as is also true for the
+primitive @code{+}).  The last method takes an arbitrary number of
+parameters@footnote{The parameter list for a @code{define-method}
+follows the conventions used for Scheme procedures. In particular it can
+use the dot notation or a symbol to denote an arbitrary number of
+parameters}.  This method acts as a kind of @code{reduce}: it calls the
+dyadic addition on the @emph{car} of the list and on the result of
+applying it on its rest.  To finish, the @code{set!} permits to redefine
+the @code{+} symbol to our extended addition.
+
+To conclude our implementation (integration?) of complex numbers, we
+could redefine standard Scheme predicates in the following manner:
 
-@node Accessing Slots
-@subsection Accessing Slots
+@lisp
+(define-method (complex? c <my-complex>) #t)
+(define-method (complex? c)           #f)
 
-The definition of a slot contains at the very least a slot name, and may
-also contain various slot options, including getter, setter and/or
-accessor functions for the slot.
+(define-method (number? n <number>) #t)
+(define-method (number? n)          #f)
+@dots{}
+@end lisp
 
-It is always possible to access slots by name, using the various
-``slot-ref'' and ``slot-set!'' procedures described in the following
-subsubsections.  For example,
+Standard primitives in which complex numbers are involved could also be
+redefined in the same manner.
 
-@example
-(define-class <my-class> ()      ;; Define a class with slots
-  (count #:init-value 0)         ;; named "count" and "cache".
-  (cache #:init-value '())
-  @dots{})
 
-(define inst (make <my-class>))  ;; Make an instance of this class.
+@node Handling Invocation Errors
+@subsection Handling Invocation Errors
 
-(slot-set! inst 'count 5)        ;; Set the value of the "count"
-                                 ;; slot to 5.
+If a generic function is invoked with a combination of parameters for
+which there is no applicable method, GOOPS raises an error.
 
-(slot-set! inst 'cache           ;; Modify the value of the
-  (cons (cons "^it" "It")        ;; "cache" slot.
-        (slot-ref inst 'cache)))
-@end example
+@deffn generic no-method
+@deffnx method no-method (gf <generic>) args
+When an application invokes a generic function, and no methods at all
+have been defined for that generic function, GOOPS calls the
+@code{no-method} generic function.  The default method calls
+@code{goops-error} with an appropriate message.
+@end deffn
 
-If a slot definition includes a getter, setter or accessor function,
-these can be used instead of @code{slot-ref} and @code{slot-set!} to
-access the slot.
+@deffn generic no-applicable-method
+@deffnx method no-applicable-method (gf <generic>) args
+When an application applies a generic function to a set of arguments,
+and no methods have been defined for those argument types, GOOPS calls
+the @code{no-applicable-method} generic function.  The default method
+calls @code{goops-error} with an appropriate message.
+@end deffn
 
-@example
-(define-class <adv-class> ()     ;; Define a new class whose slots
-  (count #:setter set-count)     ;; use a getter, a setter and
-  (cache #:accessor cache)       ;; an accessor.
-  (csize #:getter cache-size)
-  @dots{})
+@deffn generic no-next-method
+@deffnx method no-next-method (gf <generic>) args
+When a generic function method calls @code{(next-method)} to invoke the
+next less specialized method for that generic function, and no less
+specialized methods have been defined for the current generic function
+arguments, GOOPS calls the @code{no-next-method} generic function.  The
+default method calls @code{goops-error} with an appropriate message.
+@end deffn
 
-(define inst (make <adv-class>)) ;; Make an instance of this class.
 
-(set-count inst 5)               ;; Set the value of the "count"
-                                 ;; slot to 5.
+@node Inheritance
+@section Inheritance
 
-(set! (cache inst)               ;; Modify the value of the
-  (cons (cons "^it" "It")        ;; "cache" slot.
-        (cache inst)))
+Here are some class definitions to help illustrate inheritance:
 
-(let ((size (cache-size inst)))  ;; Get the value of the "csize"
-  @dots{})                           ;; slot.
-@end example
+@lisp
+(define-class A () a)
+(define-class B () b)
+(define-class C () c)
+(define-class D (A B) d a)
+(define-class E (A C) e c)
+(define-class F (D E) f)
+@end lisp
 
-Whichever of these methods is used to access slots, GOOPS always calls
-the low-level @dfn{getter} and @dfn{setter} closures for the slot to get
-and set its value.  These closures make sure that the slot behaves
-according to the @code{#:allocation} type that was specified in the slot
-definition (@pxref{Slot Options,, allocation}).  (For more about these
-closures, see @ref{Customizing Class Definition,, compute-get-n-set}.)
+@code{A}, @code{B}, @code{C} have a null list of superclasses.  In this
+case, the system will replace the null list by a list which only
+contains @code{<object>}, the root of all the classes defined by
+@code{define-class}.  @code{D}, @code{E}, @code{F} use multiple
+inheritance: each class inherits from two previously defined classes.
+Those class definitions define a hierarchy which is shown in
+@ref{fig:hier}.  In this figure, the class @code{<top>} is also shown;
+this class is the superclass of all Scheme objects.  In particular,
+@code{<top>} is the superclass of all standard Scheme
+types.
 
-@menu
-* Instance Slots::
-* Class Slots::
-* Handling Slot Access Errors::
-@end menu
+@float Figure,fig:hier
+@iftex
+@center @image{hierarchy,5in}
+@end iftex
+@ifnottex
+@verbatiminclude hierarchy.txt
+@end ifnottex
 
-@node Instance Slots
-@subsubsection Instance Slots
+@caption{A class hierarchy.}
+@end float
 
-Any slot, regardless of its allocation, can be queried, referenced and
-set using the following four primitive procedures.
+When a class has superclasses, its set of slots is calculated by taking
+the union of its own slots and those of all its superclasses.  Thus each
+instance of D will have three slots, @code{a}, @code{b} and
+@code{d}). The slots of a class can be discovered using the
+@code{class-slots} primitive.  For instance,
 
-@deffn {primitive procedure} slot-exists? obj slot-name
-Return @code{#t} if @var{obj} has a slot with name @var{slot-name},
-otherwise @code{#f}.
-@end deffn
+@lisp
+(class-slots A) @result{} ((a))
+(class-slots E) @result{} ((a) (e) (c))
+(class-slots F) @result{} ((e) (c) (b) (d) (a) (f))
+@end lisp
 
-@deffn {primitive procedure} slot-bound? obj slot-name
-Return @code{#t} if the slot named @var{slot-name} in @var{obj} has a
-value, otherwise @code{#f}.
+@noindent
+The ordering of the returned slots is not significant.
 
-@code{slot-bound?} calls the generic function @code{slot-missing} if
-@var{obj} does not have a slot called @var{slot-name} (@pxref{Handling
-Slot Access Errors, slot-missing}).
-@end deffn
+@menu
+* Class Precedence List::
+* Sorting Methods::
+@end menu
 
-@deffn {primitive procedure} slot-ref obj slot-name
-Return the value of the slot named @var{slot-name} in @var{obj}.
 
-@code{slot-ref} calls the generic function @code{slot-missing} if
-@var{obj} does not have a slot called @var{slot-name} (@pxref{Handling
-Slot Access Errors, slot-missing}).
+@node Class Precedence List
+@subsection Class Precedence List
 
-@code{slot-ref} calls the generic function @code{slot-unbound} if the
-named slot in @var{obj} does not have a value (@pxref{Handling Slot
-Access Errors, slot-unbound}).
-@end deffn
+What happens when a class inherits from two or more superclasses that
+have a slot with the same name but incompatible definitions --- for
+example, different init values or slot allocations?  We need a rule for
+deciding which slot definition the derived class ends up with, and this
+rule is provided by the class's @dfn{Class Precedence
+List}.@footnote{This section is an adaptation of material from Jeff
+Dalton's (J.Dalton@@ed.ac.uk) @cite{Brief introduction to CLOS}}
 
-@deffn {primitive procedure} slot-set! obj slot-name value
-Set the value of the slot named @var{slot-name} in @var{obj} to @var{value}.
+Another problem arises when invoking a generic function, and there is
+more than one method that could apply to the call arguments.  Here we
+need a way of ordering the applicable methods, so that Guile knows which
+method to use first, which to use next if that method calls
+@code{next-method}, and so on.  One of the ingredients for this ordering
+is determining, for each given call argument, which of the specializing
+classes, from each applicable method's definition, is the most specific
+for that argument; and here again the class precedence list helps.
 
-@code{slot-set!} calls the generic function @code{slot-missing} if
-@var{obj} does not have a slot called @var{slot-name} (@pxref{Handling
-Slot Access Errors, slot-missing}).
-@end deffn
+If inheritance was restricted such that each class could only have one
+superclass --- which is known as @dfn{single} inheritance --- class
+ordering would be easy.  The rule would be simply that a subclass is
+considered more specific than its superclass.
 
-GOOPS stores information about slots in class metaobjects.  Internally,
-all of these procedures work by looking up the slot definition for the
-slot named @var{slot-name} in the class metaobject for @code{(class-of
-@var{obj})}, and then using the slot definition's ``getter'' and
-``setter'' closures to get and set the slot value.
+With multiple inheritance, ordering is less obvious, and we have to
+impose an arbitrary rule to determine precedence. Suppose we have
 
-The next four procedures differ from the previous ones in that they take
-the class metaobject as an explicit argument, rather than assuming
-@code{(class-of @var{obj})}.  Therefore they allow you to apply the
-``getter'' and ``setter'' closures of a slot definition in one class to
-an instance of a different class.
+@lisp
+(define-class X ()
+   (x #:init-value 1))
 
-[ *fixme* I have no idea why this is useful!  Perhaps when a slot in
-@code{(class-of @var{obj})} shadows a slot with the same name in one of
-its superclasses?  There should be an enlightening example here. ]
+(define-class Y ()
+   (x #:init-value 2))
 
-@deffn {primitive procedure} slot-exists-using-class? class obj slot-name
-Return @code{#t} if the class metaobject @var{class} has a slot
-definition for a slot with name @var{slot-name}, otherwise @code{#f}.
-@end deffn
+(define-class Z (X Y)
+   (@dots{}))
+@end lisp
 
-@deffn {primitive procedure} slot-bound-using-class? class obj slot-name
-Return @code{#t} if applying @code{slot-ref-using-class} to the same
-arguments would call the generic function @code{slot-unbound}, otherwise
-@code{#f}.
+@noindent
+Clearly the @code{Z} class is more specific than @code{X} or @code{Y},
+for instances of @code{Z}.  But which is more specific out of @code{X}
+and @code{Y} --- and hence, for the definitions above, which
+@code{#:init-value} will take effect when creating an instance of
+@code{Z}?  The rule in @goops{} is that the superclasses listed earlier
+are more specific than those listed later.  Hence @code{X} is more
+specific than @code{Y}, and the @code{#:init-value} for slot @code{x} in
+instances of @code{Z} will be 1.
+
+Hence there is a linear ordering for a class and all its
+superclasses, from most specific to least specific, and this ordering is
+called the Class Precedence List of the class.
+
+In fact the rules above are not quite enough to always determine a
+unique order, but they give an idea of how things work.  For example,
+for the @code{F} class shown in @ref{fig:hier}, the class precedence
+list is
 
-@code{slot-bound-using-class?} calls the generic function
-@code{slot-missing} if @var{class} does not have a slot definition for a
-slot called @var{slot-name} (@pxref{Handling Slot Access Errors,
-slot-missing}).
-@end deffn
+@example
+(f d e a c b <object> <top>)
+@end example
 
-@deffn {primitive procedure} slot-ref-using-class class obj slot-name
-Apply the ``getter'' closure for the slot named @var{slot-name} in
-@var{class} to @var{obj}, and return its result.
+@noindent
+In cases where there is any ambiguity (like this one), it is a bad idea
+for programmers to rely on exactly what the order is.  If the order for
+some superclasses is important, it can be expressed directly in the
+class definition.
 
-@code{slot-ref-using-class} calls the generic function
-@code{slot-missing} if @var{class} does not have a slot definition for a
-slot called @var{slot-name} (@pxref{Handling Slot Access Errors,
-slot-missing}).
+The precedence list of a class can be obtained by calling
+@code{class-precedence-list}.  This function returns a ordered list
+whose first element is the most specific class.  For instance:
 
-@code{slot-ref-using-class} calls the generic function
-@code{slot-unbound} if the application of the ``getter'' closure to
-@var{obj} returns an unbound value (@pxref{Handling Slot Access Errors,
-slot-unbound}).
-@end deffn
+@lisp
+(class-precedence-list B) @result{} (#<<class> B 401b97c8> 
+                                     #<<class> <object> 401e4a10> 
+                                     #<<class> <top> 4026a9d8>)
+@end lisp
 
-@deffn {primitive procedure} slot-set-using-class! class obj slot-name value
-Apply the ``setter'' closure for the slot named @var{slot-name} in
-@var{class} to @var{obj} and @var{value}.
+@noindent
+Or for a more immediately readable result:
 
-@code{slot-set-using-class!} calls the generic function
-@code{slot-missing} if @var{class} does not have a slot definition for a
-slot called @var{slot-name} (@pxref{Handling Slot Access Errors,
-slot-missing}).
-@end deffn
+@lisp
+(map class-name (class-precedence-list B)) @result{} (B <object> <top>) 
+@end lisp
 
-@node Class Slots
-@subsubsection Class Slots
 
-Slots whose allocation is per-class rather than per-instance can be
-referenced and set without needing to specify any particular instance.
+@node Sorting Methods
+@subsection Sorting Methods
 
-@deffn procedure class-slot-ref class slot-name
-Return the value of the slot named @var{slot-name} in class @var{class}.
-The named slot must have @code{#:class} or @code{#:each-subclass}
-allocation (@pxref{Slot Options,, allocation}).
+Now, with the idea of the class precedence list, we can state precisely
+how the possible methods are sorted when more than one of the methods of
+a generic function are applicable to the call arguments.
 
-If there is no such slot with @code{#:class} or @code{#:each-subclass}
-allocation, @code{class-slot-ref} calls the @code{slot-missing} generic
-function with arguments @var{class} and @var{slot-name}.  Otherwise, if
-the slot value is unbound, @code{class-slot-ref} calls the
-@code{slot-missing} generic function, with the same arguments.
-@end deffn
+The rules are that
+@itemize
+@item
+the applicable methods are sorted in order of specificity, and the most
+specific method is used first, then the next if that method calls
+@code{next-method}, and so on
 
-@deffn procedure class-slot-set! class slot-name value
-Set the value of the slot named @var{slot-name} in class @var{class} to
-@var{value}.  The named slot must have @code{#:class} or
-@code{#:each-subclass} allocation (@pxref{Slot Options,, allocation}).
+@item
+a method M1 is more specific than another method M2 if the first
+specializing class that differs, between the definitions of M1 and M2,
+is more specific, in M1's definition, for the corresponding actual call
+argument, than the specializing class in M2's definition
 
-If there is no such slot with @code{#:class} or @code{#:each-subclass}
-allocation, @code{class-slot-ref} calls the @code{slot-missing} generic
-function with arguments @var{class} and @var{slot-name}.
-@end deffn
+@item
+a class C1 is more specific than another class C2, for an object of
+actual class C, if C1 comes before C2 in C's class precedence list.
+@end itemize
 
-@node Handling Slot Access Errors
-@subsubsection Handling Slot Access Errors
 
-GOOPS calls one of the following generic functions when a ``slot-ref''
-or ``slot-set!'' call specifies a non-existent slot name, or tries to
-reference a slot whose value is unbound.
+@node Introspection
+@section Introspection
 
-@deffn generic slot-missing
-@deffnx method slot-missing (class <class>) slot-name
-@deffnx method slot-missing (class <class>) (object <object>) slot-name
-@deffnx method slot-missing (class <class>) (object <object>) slot-name value
-When an application attempts to reference or set a class or instance
-slot by name, and the slot name is invalid for the specified @var{class}
-or @var{object}, GOOPS calls the @code{slot-missing} generic function.
+@dfn{Introspection}, or @dfn{reflection}, means being able to obtain
+information dynamically about GOOPS objects.  It is perhaps best
+illustrated by considering an object oriented language that does not
+provide any introspection, namely C++.
 
-The default methods all call @code{goops-error} with an appropriate
-message.
-@end deffn
+Nothing in C++ allows a running program to obtain answers to the following
+types of question:
 
-@deffn generic slot-unbound
-@deffnx method slot-unbound (object <object>)
-@deffnx method slot-unbound (class <class>) slot-name
-@deffnx method slot-unbound (class <class>) (object <object>) slot-name
-When an application attempts to reference a class or instance slot, and
-the slot's value is unbound, GOOPS calls the @code{slot-unbound} generic
-function.
+@itemize @bullet
+@item
+What are the data members of this object or class?
 
-The default methods all call @code{goops-error} with an appropriate
-message.
-@end deffn
+@item
+What classes does this class inherit from?
 
-@node Creating Generic Functions
-@subsection Creating Generic Functions
+@item
+Is this method call virtual or non-virtual?
 
-A generic function is a collection of methods, with rules for
-determining which of the methods should be applied for any given
-invocation of the generic function.
+@item
+If I invoke @code{Employee::adjustHoliday()}, what class contains the
+@code{adjustHoliday()} method that will be applied?
+@end itemize
 
-GOOPS represents generic functions as metaobjects of the class
-@code{<generic>} (or one of its subclasses).
+In C++, answers to such questions can only be determined by looking at
+the source code, if you have access to it.  GOOPS, on the other hand,
+includes procedures that allow answers to these questions --- or their
+GOOPS equivalents --- to be obtained dynamically, at run time.
 
 @menu
-* Basic Generic Function Creation::
-* Generic Function Internals::
-* Extending Guiles Primitives::
+* Classes::
+* Instances::
+* Slots::
+* Generic Functions::
+* Accessing Slots::
 @end menu
 
-@node Basic Generic Function Creation
-@subsubsection Basic Generic Function Creation
-
-The following forms may be used to bind a variable to a generic
-function.  Depending on that variable's pre-existing value, the generic
-function may be created empty - with no methods - or it may contain
-methods that are inferred from the pre-existing value.
-
-It is not, in general, necessary to use @code{define-generic} or
-@code{define-accessor} before defining methods for the generic function
-using @code{define-method}, since @code{define-method} will
-automatically interpolate a @code{define-generic} call, or upgrade an
-existing generic to an accessor, if that is implied by the
-@code{define-method} call.  Note in particular that,
-if the specified variable already has a @emph{generic function} value,
-@code{define-generic} and @code{define-accessor} will @emph{discard} it!
-Obviously it is application-dependent whether this is desirable or not.
-
-If, for example, you wanted to extend @code{+} for a class representing
-a new numerical type, you probably want to inherit any existing methods
-for @code{+} and so should not use @code{define-generic}.  If, on the
-other hand, you do not want to risk inheriting methods whose behaviour
-might surprise you, you can use @code{define-generic} or
-@code{define-accessor} to wipe the slate clean.
+@node Classes
+@subsection Classes
 
-@deffn syntax define-generic symbol
-Create a generic function with name @var{symbol} and bind it to the
-variable @var{symbol}.
+A GOOPS class is itself an instance of the @code{<class>} class, or of a
+subclass of @code{<class>}.  The definition of the @code{<class>} class
+has slots that are used to describe the properties of a class, including
+the following.
 
-If the variable @var{symbol} was previously bound to a Scheme procedure
-(or procedure-with-setter), the old procedure (and setter) is
-incorporated into the new generic function as its default procedure (and
-setter).  Any other previous value that was bound to @var{symbol},
-including an existing generic function, is overwritten by the new
-generic function.
+@deffn {primitive procedure} class-name class
+Return the name of class @var{class}.  This is the value of
+@var{class}'s @code{name} slot.
 @end deffn
 
-@deffn syntax define-accessor symbol
-Create an accessor with name @var{symbol} and bind it to the variable
-@var{symbol}.
+@deffn {primitive procedure} class-direct-supers class
+Return a list containing the direct superclasses of @var{class}.  This
+is the value of @var{class}'s @code{direct-supers} slot.
+@end deffn
 
-If the variable @var{symbol} was previously bound to a Scheme procedure
-(or procedure-with-setter), the old procedure (and setter) is
-incorporated into the new accessor as its default procedure (and
-setter).  Any other previous value that was bound to @var{symbol},
-including an existing generic function or accessor, is overwritten by
-the new definition.
+@deffn {primitive procedure} class-direct-slots class
+Return a list containing the slot definitions of the direct slots of
+@var{class}.  This is the value of @var{class}'s @code{direct-slots}
+slot.
 @end deffn
 
-It is sometimes tempting to use GOOPS accessors with short names.  For
-example, it is tempting to use the name @code{x} for the x-coordinate
-in vector packages.
+@deffn {primitive procedure} class-direct-subclasses class
+Return a list containing the direct subclasses of @var{class}.  This is
+the value of @var{class}'s @code{direct-subclasses} slot.
+@end deffn
 
-Assume that we work with a graphical package which needs to use two
-independent vector packages for 2D and 3D vectors respectively.  If
-both packages export @code{x} we will encounter a name collision.
+@deffn {primitive procedure} class-direct-methods class
+Return a list of all the generic function methods that use @var{class}
+as a formal parameter specializer.  This is the value of @var{class}'s
+@code{direct-methods} slot.
+@end deffn
 
-This can be resolved automagically with the duplicates handler
-@code{merge-generics} which gives the module system license to merge
-all generic functions sharing a common name:
+@deffn {primitive procedure} class-precedence-list class
+Return the class precedence list for class @var{class} (@pxref{Class
+Precedence List}).  This is the value of @var{class}'s @code{cpl} slot.
+@end deffn
 
-@smalllisp
-(define-module (math 2D-vectors)
-  :use-module (oop goops)
-  :export (x y ...))
-                 
-(define-module (math 3D-vectors)
-  :use-module (oop goops)
-  :export (x y z ...))
-
-(define-module (my-module)
-  :use-module (math 2D-vectors)
-  :use-module (math 3D-vectors)
-  :duplicates merge-generics)
-@end smalllisp
-
-The generic function @code{x} in @code{(my-module)} will now share
-methods with @code{x} in both imported modules.
+@deffn {primitive procedure} class-slots class
+Return a list containing the slot definitions for all @var{class}'s
+slots, including any slots that are inherited from superclasses.  This
+is the value of @var{class}'s @code{slots} slot.
+@end deffn
 
-There will, in fact, now be three distinct generic functions named
-@code{x}: @code{x} in @code{(2D-vectors)}, @code{x} in
-@code{(3D-vectors)}, and @code{x} in @code{(my-module)}.  The last
-function will be an @code{<extended-generic>}, extending the previous
-two functions.
+@deffn procedure class-subclasses class
+Return a list of all subclasses of @var{class}.
+@end deffn
 
-Let's call the imported generic functions the "ancestor functions".
-The generic function @code{x} in @code{(my-module)} is, in turn, a
-"descendant function" of the imported functions, extending its
-ancestors.
+@deffn procedure class-methods class
+Return a list of all methods that use @var{class} or a subclass of
+@var{class} as one of its formal parameter specializers.
+@end deffn
 
-For any generic function G, the applicable methods are selected from
-the union of the methods of the descendant functions, the methods of G
-itself and the methods of the ancestor functions.
 
-This, ancestor functions share methods with their descendants and vice
-versa.  This implies that @code{x} in @code{(math 2D-vectors)} will
-share the methods of @code{x} in @code{(my-module)} and vice versa,
-while @code{x} in @code{(math 2D-vectors)} doesn't share the methods
-of @code{x} in @code{(math 3D-vectors)}, thus preserving modularity.
+@node Instances
+@subsection Instances
 
-Sharing is dynamic, so that adding new methods to a descendant implies
-adding it to the ancestor.
+@deffn {primitive procedure} class-of value
+Return the GOOPS class of any Scheme @var{value}.
+@end deffn
 
-If duplicates checking is desired in the above example, the following
-form of the @code{:duplicates} option can be used instead:
+@deffn {primitive procedure} instance? object
+Return @code{#t} if @var{object} is any GOOPS instance, otherwise
+@code{#f}.
+@end deffn
 
-@smalllisp
-  :duplicates (merge-generics check)
-@end smalllisp
+@deffn procedure is-a? object class
+Return @code{#t} if @var{object} is an instance of @var{class} or one of
+its subclasses.
+@end deffn
 
-@node Generic Function Internals
-@subsubsection Generic Function Internals
+You can use the @code{is-a?} predicate to ask whether any given value
+belongs to a given class, or @code{class-of} to discover the class of a
+given value.  Note that when GOOPS is loaded (by code using the
+@code{(oop goops)} module) built-in classes like @code{<string>},
+@code{<list>} and @code{<number>} are automatically set up,
+corresponding to all Guile Scheme types.
 
-@code{define-generic} calls @code{ensure-generic} to upgrade a
-pre-existing procedure value, or @code{make} with metaclass
-@code{<generic>} to create a new generic function.
+@lisp
+(is-a? 2.3 <number>) @result{} #t
+(is-a? 2.3 <real>) @result{} #t
+(is-a? 2.3 <string>) @result{} #f
+(is-a? '("a" "b") <string>) @result{} #f
+(is-a? '("a" "b") <list>) @result{} #t
+(is-a? (car '("a" "b")) <string>) @result{} #t
+(is-a? <string> <class>) @result{} #t
+(is-a? <class> <string>) @result{} #f
+
+(class-of 2.3) @result{} #<<class> <real> 908c708>
+(class-of #(1 2 3)) @result{} #<<class> <vector> 908cd20>
+(class-of <string>) @result{} #<<class> <class> 8bd3e10>
+(class-of <class>) @result{} #<<class> <class> 8bd3e10>
+@end lisp
 
-@code{define-accessor} calls @code{ensure-accessor} to upgrade a
-pre-existing procedure value, or @code{make-accessor} to create a new
-accessor.
 
-@deffn procedure ensure-generic old-definition [name]
-Return a generic function with name @var{name}, if possible by using or
-upgrading @var{old-definition}.  If unspecified, @var{name} defaults to
-@code{#f}.
+@node Slots
+@subsection Slots
 
-If @var{old-definition} is already a generic function, it is returned
-unchanged.
+@deffn procedure class-slot-definition class slot-name
+Return the slot definition for the slot named @var{slot-name} in class
+@var{class}.  @var{slot-name} should be a symbol.
+@end deffn
 
-If @var{old-definition} is a Scheme procedure or procedure-with-setter,
-@code{ensure-generic} returns a new generic function that uses
-@var{old-definition} for its default procedure and setter.
+@deffn procedure slot-definition-name slot-def
+Extract and return the slot name from @var{slot-def}.
+@end deffn
 
-Otherwise @code{ensure-generic} returns a new generic function with no
-defaults and no methods.
+@deffn procedure slot-definition-options slot-def
+Extract and return the slot options from @var{slot-def}.
 @end deffn
 
-@deffn procedure make-generic [name]
-Return a new generic function with name @code{(car @var{name})}.  If
-unspecified, @var{name} defaults to @code{#f}.
+@deffn procedure slot-definition-allocation slot-def
+Extract and return the slot allocation option from @var{slot-def}.  This
+is the value of the @code{#:allocation} keyword (@pxref{Slot Options,,
+allocation}), or @code{#:instance} if the @code{#:allocation} keyword is
+absent.
 @end deffn
 
-@code{ensure-generic} calls @code{make} with metaclasses
-@code{<generic>} and @code{<generic-with-setter>}, depending on the
-previous value of the variable that it is trying to upgrade.
+@deffn procedure slot-definition-getter slot-def
+Extract and return the slot getter option from @var{slot-def}.  This is
+the value of the @code{#:getter} keyword (@pxref{Slot Options,,
+getter}), or @code{#f} if the @code{#:getter} keyword is absent.
+@end deffn
 
-@code{make-generic} is a simple wrapper for @code{make} with metaclass
-@code{<generic>}.
+@deffn procedure slot-definition-setter slot-def
+Extract and return the slot setter option from @var{slot-def}.  This is
+the value of the @code{#:setter} keyword (@pxref{Slot Options,,
+setter}), or @code{#f} if the @code{#:setter} keyword is absent.
+@end deffn
 
-@deffn procedure ensure-accessor proc [name]
-Return an accessor with name @var{name}, if possible by using or
-upgrading @var{proc}.  If unspecified, @var{name} defaults to @code{#f}.
+@deffn procedure slot-definition-accessor slot-def
+Extract and return the slot accessor option from @var{slot-def}.  This
+is the value of the @code{#:accessor} keyword (@pxref{Slot Options,,
+accessor}), or @code{#f} if the @code{#:accessor} keyword is absent.
+@end deffn
 
-If @var{proc} is already an accessor, it is returned unchanged.
+@deffn procedure slot-definition-init-value slot-def
+Extract and return the slot init-value option from @var{slot-def}.  This
+is the value of the @code{#:init-value} keyword (@pxref{Slot Options,,
+init-value}), or the unbound value if the @code{#:init-value} keyword is
+absent.
+@end deffn
 
-If @var{proc} is a Scheme procedure, procedure-with-setter or generic
-function, @code{ensure-accessor} returns an accessor that reuses the
-reusable elements of @var{proc}.
+@deffn procedure slot-definition-init-form slot-def
+Extract and return the slot init-form option from @var{slot-def}.  This
+is the value of the @code{#:init-form} keyword (@pxref{Slot Options,,
+init-form}), or the unbound value if the @code{#:init-form} keyword is
+absent.
+@end deffn
 
-Otherwise @code{ensure-accessor} returns a new accessor with no defaults
-and no methods.
+@deffn procedure slot-definition-init-thunk slot-def
+Extract and return the slot init-thunk option from @var{slot-def}.  This
+is the value of the @code{#:init-thunk} keyword (@pxref{Slot Options,,
+init-thunk}), or @code{#f} if the @code{#:init-thunk} keyword is absent.
 @end deffn
 
-@deffn procedure make-accessor [name]
-Return a new accessor with name @code{(car @var{name})}.  If
-unspecified, @var{name} defaults to @code{#f}.
+@deffn procedure slot-definition-init-keyword slot-def
+Extract and return the slot init-keyword option from @var{slot-def}.
+This is the value of the @code{#:init-keyword} keyword (@pxref{Slot
+Options,, init-keyword}), or @code{#f} if the @code{#:init-keyword}
+keyword is absent.
 @end deffn
 
-@code{ensure-accessor} calls @code{make} with
-metaclass @code{<generic-with-setter>}, as well as calls to
-@code{ensure-generic}, @code{make-accessor} and (tail recursively)
-@code{ensure-accessor}.
+@deffn procedure slot-init-function class slot-name
+Return the initialization function for the slot named @var{slot-name} in
+class @var{class}.  @var{slot-name} should be a symbol.
 
-@code{make-accessor} calls @code{make} twice, first
-with metaclass @code{<generic>} to create a generic function for the
-setter, then with metaclass @code{<generic-with-setter>} to create the
-accessor, passing the setter generic function as the value of the
-@code{#:setter} keyword.
+The returned initialization function incorporates the effects of the
+standard @code{#:init-thunk}, @code{#:init-form} and @code{#:init-value}
+slot options.  These initializations can be overridden by the
+@code{#:init-keyword} slot option or by a specialized @code{initialize}
+method, so, in general, the function returned by
+@code{slot-init-function} may be irrelevant.  For a fuller discussion,
+see @ref{Slot Options,, init-value}.
+@end deffn
 
-@node Extending Guiles Primitives
-@subsubsection Extending Guile's Primitives
 
-When GOOPS is loaded, many of Guile's primitive procedures can be
-extended by giving them a generic function definition that operates
-in conjunction with their normal C-coded implementation.  For
-primitives that are extended in this way, the result from the user-
-or application-level point of view is that the extended primitive
-behaves exactly like a generic function with the C-coded implementation
-as its default method.
+@node Generic Functions
+@subsection Generic Functions
 
-The @code{generic-capability?} predicate should be used to determine
-whether a particular primitive is extensible in this way.
+A generic function is an instance of the @code{<generic>} class, or of a
+subclass of @code{<generic>}.  The definition of the @code{<generic>}
+class has slots that are used to describe the properties of a generic
+function.
 
-@deffn {primitive procedure} generic-capability? primitive
-Return @code{#t} if @var{primitive} can be extended by giving it a
-generic function definition, otherwise @code{#f}.
+@deffn {primitive procedure} generic-function-name gf
+Return the name of generic function @var{gf}.
 @end deffn
 
-Even when a primitive procedure is extensible like this, its generic
-function definition is not created until it is needed by a call to
-@code{define-method}, or until the application explicitly requests it
-by calling @code{enable-primitive-generic!}.
-
-@deffn {primitive procedure} enable-primitive-generic! primitive
-Force the creation of a generic function definition for
-@var{primitive}.
+@deffn {primitive procedure} generic-function-methods gf
+Return a list of the methods of generic function @var{gf}.  This is the
+value of @var{gf}'s @code{methods} slot.
 @end deffn
 
-Once the generic function definition for a primitive has been created,
-it can be retrieved using @code{primitive-generic-generic}.
+Similarly, a method is an instance of the @code{<method>} class, or of a
+subclass of @code{<method>}; and the definition of the @code{<method>}
+class has slots that are used to describe the properties of a method.
 
-@deffn {primitive procedure} primitive-generic-generic primitive
-Return the generic function definition of @var{primitive}.
+@deffn {primitive procedure} method-generic-function method
+Return the generic function that @var{method} belongs to.  This is the
+value of @var{method}'s @code{generic-function} slot.
+@end deffn
 
-@code{primitive-generic-generic} raises an error if @var{primitive}
-is not a primitive with generic capability, or if its generic capability
-has not yet been enabled, whether implicitly (by @code{define-method})
-or explicitly (by @code{enable-primitive-generic!}).
+@deffn {primitive procedure} method-specializers method
+Return a list of @var{method}'s formal parameter specializers .  This is
+the value of @var{method}'s @code{specializers} slot.
 @end deffn
 
-Note that the distinction between, on the one hand, primitives with
-additional generic function definitions and, on the other hand, generic
-functions with a default method, may disappear when GOOPS is fully
-integrated into the core of Guile.  Consequently, the
-procedures described in this section may disappear as well.
+@deffn {primitive procedure} method-procedure method
+Return the procedure that implements @var{method}.  This is the value of
+@var{method}'s @code{procedure} slot.
+@end deffn
 
-@node Adding Methods to Generic Functions
-@subsection Adding Methods to Generic Functions
+@deffn generic method-source
+@deffnx method method-source (m <method>)
+Return an expression that prints to show the definition of method
+@var{m}.
 
-@menu
-* Basic Method Definition::
-* Method Definition Internals::
-@end menu
+@example
+(define-generic cube)
 
-@node Basic Method Definition
-@subsubsection Basic Method Definition
+(define-method (cube (n <number>))
+  (* n n n))
 
-To add a method to a generic function, use the @code{define-method} form.
+(map method-source (generic-function-methods cube))
+@result{}
+((method ((n <number>)) (* n n n)))
+@end example
+@end deffn
 
-@deffn syntax define-method (generic parameter @dots{}) . body
-Define a method for the generic function or accessor @var{generic} with
-parameters @var{parameter}s and body @var{body}.
 
-@var{generic} is a generic function.  If @var{generic} is a variable
-which is not yet bound to a generic function object, the expansion of
-@code{define-method} will include a call to @code{define-generic}.  If
-@var{generic} is @code{(setter @var{generic-with-setter})}, where
-@var{generic-with-setter} is a variable which is not yet bound to a
-generic-with-setter object, the expansion will include a call to
-@code{define-accessor}.
+@node Accessing Slots
+@subsection Accessing Slots
 
-Each @var{parameter} must be either a symbol or a two-element list
-@code{(@var{symbol} @var{class})}.  The symbols refer to variables in
-the @var{body} that will be bound to the parameters supplied by the
-caller when calling this method.  The @var{class}es, if present,
-specify the possible combinations of parameters to which this method
-can be applied.
+Any slot, regardless of its allocation, can be queried, referenced and
+set using the following four primitive procedures.
 
-@var{body} is the body of the method definition.
+@deffn {primitive procedure} slot-exists? obj slot-name
+Return @code{#t} if @var{obj} has a slot with name @var{slot-name},
+otherwise @code{#f}.
 @end deffn
 
-@code{define-method} expressions look a little like normal Scheme
-procedure definitions of the form
+@deffn {primitive procedure} slot-bound? obj slot-name
+Return @code{#t} if the slot named @var{slot-name} in @var{obj} has a
+value, otherwise @code{#f}.
 
-@example
-(define (name formals @dots{}) . body)
-@end example
+@code{slot-bound?} calls the generic function @code{slot-missing} if
+@var{obj} does not have a slot called @var{slot-name} (@pxref{Accessing
+Slots, slot-missing}).
+@end deffn
 
-The most important difference is that each formal parameter, apart from the
-possible ``rest'' argument, can be qualified by a class name:
-@code{@var{formal}} becomes @code{(@var{formal} @var{class})}.  The
-meaning of this qualification is that the method being defined
-will only be applicable in a particular generic function invocation if
-the corresponding argument is an instance of @code{@var{class}} (or one of
-its subclasses).  If more than one of the formal parameters is qualified
-in this way, then the method will only be applicable if each of the
-corresponding arguments is an instance of its respective qualifying class.
+@deffn {primitive procedure} slot-ref obj slot-name
+Return the value of the slot named @var{slot-name} in @var{obj}.
 
-Note that unqualified formal parameters act as though they are qualified
-by the class @code{<top>}, which GOOPS uses to mean the superclass of
-all valid Scheme types, including both primitive types and GOOPS classes.
+@code{slot-ref} calls the generic function @code{slot-missing} if
+@var{obj} does not have a slot called @var{slot-name} (@pxref{Accessing
+Slots, slot-missing}).
 
-For example, if a generic function method is defined with
-@var{parameter}s @code{((s1 <square>) (n <number>))}, that method is
-only applicable to invocations of its generic function that have two
-parameters where the first parameter is an instance of the
-@code{<square>} class and the second parameter is a number.
+@code{slot-ref} calls the generic function @code{slot-unbound} if the
+named slot in @var{obj} does not have a value (@pxref{Accessing Slots,
+slot-unbound}).
+@end deffn
 
-If a generic function is invoked with a combination of parameters for which
-there is no applicable method, GOOPS raises an error.  For more about
-invocation error handling, and generic function invocation in general,
-see @ref{Invoking Generic Functions}.
+@deffn {primitive procedure} slot-set! obj slot-name value
+Set the value of the slot named @var{slot-name} in @var{obj} to @var{value}.
 
-@node Method Definition Internals
-@subsubsection Method Definition Internals
+@code{slot-set!} calls the generic function @code{slot-missing} if
+@var{obj} does not have a slot called @var{slot-name} (@pxref{Accessing
+Slots, slot-missing}).
+@end deffn
 
-@code{define-method}
+GOOPS stores information about slots in classes.  Internally,
+all of these procedures work by looking up the slot definition for the
+slot named @var{slot-name} in the class @code{(class-of
+@var{obj})}, and then using the slot definition's ``getter'' and
+``setter'' closures to get and set the slot value.
 
-@itemize @bullet
-@item
-checks the form of the first parameter, and applies the following steps
-to the accessor's setter if it has the @code{(setter @dots{})} form
+The next four procedures differ from the previous ones in that they take
+the class as an explicit argument, rather than assuming
+@code{(class-of @var{obj})}.  Therefore they allow you to apply the
+``getter'' and ``setter'' closures of a slot definition in one class to
+an instance of a different class.
 
-@item
-interpolates a call to @code{define-generic} or @code{define-accessor}
-if a generic function is not already defined with the supplied name
+@deffn {primitive procedure} slot-exists-using-class? class obj slot-name
+Return @code{#t} if @var{class} has a slot definition for a slot with
+name @var{slot-name}, otherwise @code{#f}.
+@end deffn
 
-@item
-calls @code{method} with the @var{parameter}s and @var{body}, to make a
-new method instance
+@deffn {primitive procedure} slot-bound-using-class? class obj slot-name
+Return @code{#t} if applying @code{slot-ref-using-class} to the same
+arguments would call the generic function @code{slot-unbound}, otherwise
+@code{#f}.
 
-@item
-calls @code{add-method!} to add this method to the relevant generic
-function.
-@end itemize
+@code{slot-bound-using-class?} calls the generic function
+@code{slot-missing} if @var{class} does not have a slot definition for a
+slot called @var{slot-name} (@pxref{Accessing Slots,
+slot-missing}).
+@end deffn
 
-@deffn syntax method (parameter @dots{}) . body
-Make a method whose specializers are defined by the classes in
-@var{parameter}s and whose procedure definition is constructed from the
-@var{parameter} symbols and @var{body} forms.
-
-The @var{parameter} and @var{body} parameters should be as for
-@code{define-method} (@pxref{Basic Method Definition,, define-method}).
-@end deffn
+@deffn {primitive procedure} slot-ref-using-class class obj slot-name
+Apply the ``getter'' closure for the slot named @var{slot-name} in
+@var{class} to @var{obj}, and return its result.
 
-@code{method}
+@code{slot-ref-using-class} calls the generic function
+@code{slot-missing} if @var{class} does not have a slot definition for a
+slot called @var{slot-name} (@pxref{Accessing Slots,
+slot-missing}).
 
-@itemize @bullet
-@item
-extracts formals and specializing classes from the @var{parameter}s,
-defaulting the class for unspecialized parameters to @code{<top>}
+@code{slot-ref-using-class} calls the generic function
+@code{slot-unbound} if the application of the ``getter'' closure to
+@var{obj} returns an unbound value (@pxref{Accessing Slots,
+slot-unbound}).
+@end deffn
 
-@item
-creates a closure using the formals and the @var{body} forms
+@deffn {primitive procedure} slot-set-using-class! class obj slot-name value
+Apply the ``setter'' closure for the slot named @var{slot-name} in
+@var{class} to @var{obj} and @var{value}.
 
-@item
-calls @code{make} with metaclass @code{<method>} and the specializers
-and closure using the @code{#:specializers} and @code{#:procedure}
-keywords.
-@end itemize
+@code{slot-set-using-class!} calls the generic function
+@code{slot-missing} if @var{class} does not have a slot definition for a
+slot called @var{slot-name} (@pxref{Accessing Slots, slot-missing}).
+@end deffn
 
-@deffn procedure make-method specializers procedure
-Make a method using @var{specializers} and @var{procedure}.
+Slots whose allocation is per-class rather than per-instance can be
+referenced and set without needing to specify any particular instance.
 
-@var{specializers} should be a list of classes that specifies the
-parameter combinations to which this method will be applicable.
+@deffn procedure class-slot-ref class slot-name
+Return the value of the slot named @var{slot-name} in class @var{class}.
+The named slot must have @code{#:class} or @code{#:each-subclass}
+allocation (@pxref{Slot Options,, allocation}).
 
-@var{procedure} should be the closure that will applied to the generic
-function parameters when this method is invoked.
+If there is no such slot with @code{#:class} or @code{#:each-subclass}
+allocation, @code{class-slot-ref} calls the @code{slot-missing} generic
+function with arguments @var{class} and @var{slot-name}.  Otherwise, if
+the slot value is unbound, @code{class-slot-ref} calls the
+@code{slot-unbound} generic function, with the same arguments.
 @end deffn
 
-@code{make-method} is a simple wrapper around @code{make} with metaclass
-@code{<method>}.
-
-@deffn generic add-method! target method
-Generic function for adding method @var{method} to @var{target}.
-@end deffn
+@deffn procedure class-slot-set! class slot-name value
+Set the value of the slot named @var{slot-name} in class @var{class} to
+@var{value}.  The named slot must have @code{#:class} or
+@code{#:each-subclass} allocation (@pxref{Slot Options,, allocation}).
 
-@deffn method add-method! (generic <generic>) (method <method>)
-Add method @var{method} to the generic function @var{generic}.
+If there is no such slot with @code{#:class} or @code{#:each-subclass}
+allocation, @code{class-slot-ref} calls the @code{slot-missing} generic
+function with arguments @var{class} and @var{slot-name}.
 @end deffn
 
-@deffn method add-method! (proc <procedure>) (method <method>)
-If @var{proc} is a procedure with generic capability (@pxref{Extending
-Guiles Primitives,, generic-capability?}), upgrade it to a
-primitive generic and add @var{method} to its generic function
-definition.
-@end deffn
+When a @code{slot-ref} or @code{slot-set!} call specifies a non-existent
+slot name, or tries to reference a slot whose value is unbound, GOOPS
+calls one of the following generic functions.
 
-@deffn method add-method! (pg <primitive-generic>) (method <method>)
-Add method @var{method} to the generic function definition of @var{pg}.
+@deffn generic slot-missing
+@deffnx method slot-missing (class <class>) slot-name
+@deffnx method slot-missing (class <class>) (object <object>) slot-name
+@deffnx method slot-missing (class <class>) (object <object>) slot-name value
+When an application attempts to reference or set a class or instance
+slot by name, and the slot name is invalid for the specified @var{class}
+or @var{object}, GOOPS calls the @code{slot-missing} generic function.
 
-Implementation: @code{(add-method! (primitive-generic-generic pg) method)}.
+The default methods all call @code{goops-error} with an appropriate
+message.
 @end deffn
 
-@deffn method add-method! (whatever <top>) (method <method>)
-Raise an error indicating that @var{whatever} is not a valid generic
+@deffn generic slot-unbound
+@deffnx method slot-unbound (object <object>)
+@deffnx method slot-unbound (class <class>) slot-name
+@deffnx method slot-unbound (class <class>) (object <object>) slot-name
+When an application attempts to reference a class or instance slot, and
+the slot's value is unbound, GOOPS calls the @code{slot-unbound} generic
 function.
+
+The default methods all call @code{goops-error} with an appropriate
+message.
 @end deffn
 
-@node Invoking Generic Functions
-@subsection Invoking Generic Functions
 
-When a variable with a generic function definition appears as the first
-element of a list that is being evaluated, the Guile evaluator tries
-to apply the generic function to the arguments obtained by evaluating
-the remaining elements of the list.  [ *fixme* How do I put this in a
-more Schemely and less Lispy way? ]
+@node GOOPS Error Handling
+@section Error Handling
 
-Usually a generic function contains several method definitions, with
-varying degrees of formal parameter specialization (@pxref{Basic
-Method Definition,, define-method}).  So it is necessary to sort these
-methods by specificity with respect to the supplied arguments, and then
-apply the most specific method definition.  Less specific methods
-may be applied subsequently if a method that is being applied calls
-@code{next-method}.
+The procedure @code{goops-error} is called to raise an appropriate error
+by the default methods of the following generic functions:
 
-@menu
-* Determining Which Methods to Apply::
-* Handling Invocation Errors::
-@end menu
+@itemize @bullet
+@item
+@code{slot-missing} (@pxref{Accessing Slots,, slot-missing})
 
-@node Determining Which Methods to Apply
-@subsubsection Determining Which Methods to Apply
+@item
+@code{slot-unbound} (@pxref{Accessing Slots,, slot-unbound})
 
-[ *fixme*  Sorry - this is the area of GOOPS that I understand least of
-all, so I'm afraid I have to pass on this section.  Would some other
-kind person consider filling it in? ]
+@item
+@code{no-method} (@pxref{Handling Invocation Errors,, no-method})
 
-@deffn generic apply-generic
-@deffnx method apply-generic (gf <generic>) args
-@end deffn
+@item
+@code{no-applicable-method} (@pxref{Handling Invocation Errors,,
+no-applicable-method})
 
-@deffn generic compute-applicable-methods
-@deffnx method compute-applicable-methods (gf <generic>) args
-@end deffn
+@item
+@code{no-next-method} (@pxref{Handling Invocation Errors,,
+no-next-method})
+@end itemize
 
-@deffn generic sort-applicable-methods
-@deffnx method sort-applicable-methods (gf <generic>) methods args
-@end deffn
+If you customize these functions for particular classes or metaclasses,
+you may still want to use @code{goops-error} to signal any error
+conditions that you detect.
 
-@deffn generic method-more-specific?
-@deffnx method method-more-specific? (m1 <method>) (m2 <method>) args
+@deffn procedure goops-error format-string arg @dots{}
+Raise an error with key @code{goops-error} and error message constructed
+from @var{format-string} and @var{arg} @enddots{}.  Error message
+formatting is as done by @code{scm-error}.
 @end deffn
 
-@deffn generic apply-method
-@deffnx method apply-method (gf <generic>) methods build-next args
-@end deffn
 
-@deffn generic apply-methods
-@deffnx method apply-methods (gf <generic>) (l <list>) args
-@end deffn
+@node GOOPS Object Miscellany
+@section GOOPS Object Miscellany
 
-@node Handling Invocation Errors
-@subsubsection Handling Invocation Errors
+Here we cover some points about GOOPS objects that aren't substantial
+enough to merit sections on their own.
 
-@deffn generic no-method
-@deffnx method no-method (gf <generic>) args
-When an application invokes a generic function, and no methods at all
-have been defined for that generic function, GOOPS calls the
-@code{no-method} generic function.  The default method calls
-@code{goops-error} with an appropriate message.
-@end deffn
+@subheading Object Equality
 
-@deffn generic no-applicable-method
-@deffnx method no-applicable-method (gf <generic>) args
-When an application applies a generic function to a set of arguments,
-and no methods have been defined for those argument types, GOOPS calls
-the @code{no-applicable-method} generic function.  The default method
-calls @code{goops-error} with an appropriate message.
-@end deffn
+When GOOPS is loaded, @code{eqv?}, @code{equal?} and @code{=} become
+generic functions, and you can define methods for them, specialized for
+your own classes, so as to control what the various kinds of equality
+mean for your classes.
 
-@deffn generic no-next-method
-@deffnx method no-next-method (gf <generic>) args
-When a generic function method calls @code{(next-method)} to invoke the
-next less specialized method for that generic function, and no less
-specialized methods have been defined for the current generic function
-arguments, GOOPS calls the @code{no-next-method} generic function.  The
-default method calls @code{goops-error} with an appropriate message.
-@end deffn
+For example, the @code{assoc} procedure, for looking up an entry in an
+alist, is specified as using @code{equal?} to determine when the car of
+an entry in the alist is the same as the key parameter that @code{assoc}
+is called with.  Hence, if you had defined a new class, and wanted to
+use instances of that class as the keys in an alist, you could define a
+method for @code{equal?}, for your class, to control @code{assoc}'s
+lookup precisely.
 
-@node Redefining a Class
-@subsection Redefining a Class
+@subheading Cloning Objects
 
-Suppose that a class @code{<my-class>} is defined using @code{define-class}
-(@pxref{Basic Class Definition,, define-class}), with slots that have
-accessor functions, and that an application has created several instances
-of @code{<my-class>} using @code{make} (@pxref{Basic Instance Creation,,
-make}).  What then happens if @code{<my-class>} is redefined by calling
-@code{define-class} again?
+@deffn generic shallow-clone
+@deffnx method shallow-clone (self <object>)
+Return a ``shallow'' clone of @var{self}.  The default method makes a
+shallow clone by allocating a new instance and copying slot values from
+self to the new instance.  Each slot value is copied either as an
+immediate value or by reference.
+@end deffn
 
-@menu
-* Default Class Redefinition Behaviour::
-* Customizing Class Redefinition::
-@end menu
+@deffn generic deep-clone
+@deffnx method deep-clone (self <object>)
+Return a ``deep'' clone of @var{self}.  The default method makes a deep
+clone by allocating a new instance and copying or cloning slot values
+from self to the new instance.  If a slot value is an instance
+(satisfies @code{instance?}), it is cloned by calling @code{deep-clone}
+on that value.  Other slot values are copied either as immediate values
+or by reference.
+@end deffn
 
-@node Default Class Redefinition Behaviour
-@subsubsection Default Class Redefinition Behaviour
+@subheading Write and Display
 
-GOOPS' default answer to this question is as follows.
+@deffn {primitive generic} write object port
+@deffnx {primitive generic} display object port
+When GOOPS is loaded, @code{write} and @code{display} become generic
+functions with special methods for printing
 
 @itemize @bullet
 @item
-All existing direct instances of @code{<my-class>} are converted to be
-instances of the new class.  This is achieved by preserving the values
-of slots that exist in both the old and new definitions, and initializing the
-values of new slots in the usual way (@pxref{Basic Instance Creation,,
-make}).
+objects - instances of the class @code{<object>}
 
 @item
-All existing subclasses of @code{<my-class>} are redefined, as though
-the @code{define-class} expressions that defined them were re-evaluated
-following the redefinition of @code{<my-class>}, and the class
-redefinition process described here is applied recursively to the
-redefined subclasses.
+foreign objects - instances of the class @code{<foreign-object>}
 
 @item
-Once all of its instances and subclasses have been updated, the class
-metaobject previously bound to the variable @code{<my-class>} is no
-longer needed and so can be allowed to be garbage collected.
-@end itemize
-
-To keep things tidy, GOOPS also needs to do a little housekeeping on
-methods that are associated with the redefined class.
+classes - instances of the class @code{<class>}
 
-@itemize @bullet
 @item
-Slot accessor methods for slots in the old definition should be removed
-from their generic functions.  They will be replaced by accessor methods
-for the slots of the new class definition.
+generic functions - instances of the class @code{<generic>}
 
 @item
-Any generic function method that uses the old @code{<my-class>} metaobject
-as one of its formal parameter specializers must be updated to refer to
-the new @code{<my-class>} metaobject.  (Whenever a new generic function
-method is defined, @code{define-method} adds the method to a list stored
-in the class metaobject for each class used as a formal parameter
-specializer, so it is easy to identify all the methods that must be
-updated when a class is redefined.)
+methods - instances of the class @code{<method>}.
 @end itemize
 
-If this class redefinition strategy strikes you as rather counter-intuitive,
-bear in mind that it is derived from similar behaviour in other object
-systems such as CLOS, and that experience in those systems has shown it to be
-very useful in practice.
-
-Also bear in mind that, like most of GOOPS' default behaviour, it can
-be customized@dots{}
+@code{write} and @code{display} print non-GOOPS values in the same way
+as the Guile primitive @code{write} and @code{display} functions.
+@end deffn
 
-@node Customizing Class Redefinition
-@subsubsection Customizing Class Redefinition
+In addition to the cases mentioned, you can of course define
+@code{write} and @code{display} methods for your own classes, to
+customize how instances of those classes are printed.
 
-When @code{define-class} notices that a class is being redefined,
-it constructs the new class metaobject as usual, and then invokes the
-@code{class-redefinition} generic function with the old and new classes
-as arguments.  Therefore, if the old or new classes have metaclasses
-other than the default @code{<class>}, class redefinition behaviour can
-be customized by defining a @code{class-redefinition} method that is
-specialized for the relevant metaclasses.
 
-@deffn generic class-redefinition
-Handle the class redefinition from @var{old-class} to @var{new-class},
-and return the new class metaobject that should be bound to the
-variable specified by @code{define-class}'s first argument.
-@end deffn
+@node The Metaobject Protocol
+@section The Metaobject Protocol
 
-@deffn method class-redefinition (old-class <class>) (new-class <class>)
-Implements GOOPS' default class redefinition behaviour, as described in
-@ref{Default Class Redefinition Behaviour}.  Returns the metaobject
-for the new class definition.
-@end deffn
+At this point, we've said about as much as can be said about GOOPS
+without having to confront the idea of the metaobject protocol.  There
+are a couple more topics that could be discussed in isolation first ---
+class redefinition, and changing the class of existing instances --- but
+in practice developers using them will be advanced enough to want to
+understand the metaobject protocol too, and will probably be using the
+protocol to customize exactly what happens during these events.
 
-An alternative class redefinition strategy could be to leave all
-existing instances as instances of the old class, but accepting that the
-old class is now ``nameless'', since its name has been taken over by the
-new definition.  In this strategy, any existing subclasses could also
-be left as they are, on the understanding that they inherit from a nameless
-superclass.
+So let's plunge in.  GOOPS is based on a ``metaobject protocol'' (aka
+``MOP'') derived from the ones used in CLOS (the Common Lisp Object
+System), tiny-clos (a small Scheme implementation of a subset of CLOS
+functionality) and STKlos.
 
-This strategy is easily implemented in GOOPS, by defining a new metaclass,
-that will be used as the metaclass for all classes to which the strategy
-should apply, and then defining a @code{class-redefinition} method that
-is specialized for this metaclass:
+The MOP underlies many possible GOOPS customizations --- such as
+defining an @code{initialize} method to customize the initialization of
+instances of an application-defined class --- and an understanding of
+the MOP makes it much easier to explain such customizations in a precise
+way.  And at a deeper level, understanding the MOP is a key part of
+understanding GOOPS, and of taking full advantage of GOOPS' power, by
+customizing the behaviour of GOOPS itself.
 
-@example
-(define-class <can-be-nameless> (<class>))
+@menu
+* Metaobjects and the Metaobject Protocol::
+* Metaclasses::
+* MOP Specification::
+* Instance Creation Protocol::
+* Class Definition Protocol::
+* Customizing Class Definition::
+* Method Definition::
+* Method Definition Internals::
+* Generic Function Internals::
+* Generic Function Invocation::
+@end menu
 
-(define-method (class-redefinition (old <can-be-nameless>)
-                                   (new <class>))
-  new)
-@end example
+@node Metaobjects and the Metaobject Protocol
+@subsection Metaobjects and the Metaobject Protocol
 
-When customization can be as easy as this, aren't you glad that GOOPS
-implements the far more difficult strategy as its default!
+The building blocks of GOOPS are classes, slot definitions, instances,
+generic functions and methods.  A class is a grouping of inheritance
+relations and slot definitions.  An instance is an object with slots
+that are allocated following the rules implied by its class's
+superclasses and slot definitions.  A generic function is a collection
+of methods and rules for determining which of those methods to apply
+when the generic function is invoked.  A method is a procedure and a set
+of specializers that specify the type of arguments to which the
+procedure is applicable.
+
+Of these entities, GOOPS represents classes, generic functions and
+methods as ``metaobjects''.  In other words, the values in a GOOPS
+program that describe classes, generic functions and methods, are
+themselves instances (or ``objects'') of special GOOPS classes that
+encapsulate the behaviour, respectively, of classes, generic functions,
+and methods.
+
+(The other two entities are slot definitions and instances.  Slot
+definitions are not strictly instances, but every slot definition is
+associated with a GOOPS class that specifies the behaviour of the slot
+as regards accessibility and protection from garbage collection.
+Instances are of course objects in the usual sense, and there is no
+benefit from thinking of them as metaobjects.)
+
+The ``metaobject protocol'' (or ``MOP'') is the specification of the
+generic functions which determine the behaviour of these metaobjects and
+the circumstances in which these generic functions are invoked.
+
+For a concrete example of what this means, consider how GOOPS calculates
+the set of slots for a class that is being defined using
+@code{define-class}.  The desired set of slots is the union of the new
+class's direct slots and the slots of all its superclasses.  But
+@code{define-class} itself does not perform this calculation.  Instead,
+there is a method of the @code{initialize} generic function that is
+specialized for instances of type @code{<class>}, and it is this method
+that performs the slot calculation.
 
-Finally, note that, if @code{class-redefinition} itself is not customized,
-the default @code{class-redefinition} method invokes three further
-generic functions that could be individually customized:
+@code{initialize} is a generic function which GOOPS calls whenever a new
+instance is created, immediately after allocating memory for a new
+instance, in order to initialize the new instance's slots.  The sequence
+of steps is as follows.
 
 @itemize @bullet
 @item
-(remove-class-accessors! @var{old-class})
+@code{define-class} uses @code{make} to make a new instance of the
+@code{<class>} class, passing as initialization arguments the
+superclasses, slot definitions and class options that were specified in
+the @code{define-class} form.
 
 @item
-(update-direct-method! @var{method} @var{old-class} @var{new-class})
+@code{make} allocates memory for the new instance, and invokes the
+@code{initialize} generic function to initialize the new instance's
+slots.
 
 @item
-(update-direct-subclass! @var{subclass} @var{old-class} @var{new-class})
+The @code{initialize} generic function applies the method that is
+specialized for instances of type @code{<class>}, and this method
+performs the slot calculation.
 @end itemize
 
-and the default methods for these generic functions invoke further
-generic functions, and so on@dots{}  The detailed protocol for all of these
-is described in @ref{MOP Specification}.
+In other words, rather than being hardcoded in @code{define-class}, the
+default behaviour of class definition is encapsulated by generic
+function methods that are specialized for the class @code{<class>}.
 
-@node Changing the Class of an Instance
-@subsection Changing the Class of an Instance
+It is possible to create a new class that inherits from @code{<class>},
+which is called a ``metaclass'', and to write a new @code{initialize}
+method that is specialized for instances of the new metaclass.  Then, if
+the @code{define-class} form includes a @code{#:metaclass} class option
+whose value is the new metaclass, the class that is defined by the
+@code{define-class} form will be an instance of the new metaclass rather
+than of the default @code{<class>}, and will be defined in accordance
+with the new @code{initialize} method.  Thus the default slot
+calculation, as well as any other aspect of the new class's relationship
+with its superclasses, can be modified or overridden.
 
-You can change the class of an existing instance by invoking the
-generic function @code{change-class} with two arguments: the instance
-and the new class.
+In a similar way, the behaviour of generic functions can be modified or
+overridden by creating a new class that inherits from the standard
+generic function class @code{<generic>}, writing appropriate methods
+that are specialized to the new class, and creating new generic
+functions that are instances of the new class.
 
-@deffn generic change-class
-@end deffn
+The same is true for method metaobjects.  And the same basic mechanism
+allows the application class author to write an @code{initialize} method
+that is specialized to their application class, to initialize instances
+of that class.
 
-The default method for @code{change-class} decides how to implement the
-change of class by looking at the slot definitions for the instance's
-existing class and for the new class.  If the new class has slots with
-the same name as slots in the existing class, the values for those slots
-are preserved.  Slots that are present only in the existing class are
-discarded.  Slots that are present only in the new class are initialized
-using the corresponding slot definition's init function (@pxref{Classes,,
-slot-init-function}).
+Such is the power of the MOP.  Note that @code{initialize} is just one
+of a large number of generic functions that can be customized to modify
+the behaviour of application objects and classes and of GOOPS itself.
+Each following section covers a particular area of GOOPS functionality,
+and describes the generic functions that are relevant for customization
+of that area.
 
-@deffn {method} change-class (obj <object>) (new <class>)
-Modify instance @var{obj} to make it an instance of class @var{new}.
+@node Metaclasses
+@subsection Metaclasses
 
-The value of each of @var{obj}'s slots is preserved only if a similarly named
-slot exists in @var{new}; any other slot values are discarded.
+A @dfn{metaclass} is the class of an object which represents a GOOPS
+class.  Put more succinctly, a metaclass is a class's class.
 
-The slots in @var{new} that do not correspond to any of @var{obj}'s
-pre-existing slots are initialized according to @var{new}'s slot definitions'
-init functions.
-@end deffn
+Most GOOPS classes have the metaclass @code{<class>} and, by default,
+any new class that is created using @code{define-class} has the
+metaclass @code{<class>}.
 
-Customized change of class behaviour can be implemented by defining
-@code{change-class} methods that are specialized either by the class
-of the instances to be modified or by the metaclass of the new class.
+But what does this really mean?  To find out, let's look in more detail
+at what happens when a new class is created using @code{define-class}:
+
+@example
+(define-class <my-class> (<object>) . slots)
+@end example
 
-When a class is redefined (@pxref{Redefining a Class}), and the default
-class redefinition behaviour is not overridden, GOOPS (eventually)
-invokes the @code{change-class} generic function for each existing
-instance of the redefined class.
+@noindent
+Guile expands this to something like:
 
-@node Introspection
-@subsection Introspection
+@example
+(define <my-class> (class (<object>) . slots))
+@end example
 
-@dfn{Introspection}, also known as @dfn{reflection}, is the name given
-to the ability to obtain information dynamically about GOOPS metaobjects.
-It is perhaps best illustrated by considering an object oriented language
-that does not provide any introspection, namely C++.
+@noindent
+which in turn expands to:
 
-Nothing in C++ allows a running program to obtain answers to the following
-types of question:
+@example
+(define <my-class>
+  (make <class> #:dsupers (list <object>) #:slots slots))
+@end example
+
+As this expansion makes clear, the resulting value of @code{<my-class>}
+is an instance of the class @code{<class>} with slot values specifying
+the superclasses and slot definitions for the class @code{<my-class>}.
+(@code{#:dsupers} and @code{#:slots} are initialization keywords for the
+@code{dsupers} and @code{dslots} slots of the @code{<class>} class.)
+
+Now suppose that you want to define a new class with a metaclass other
+than the default @code{<class>}.  This is done by writing:
+
+@example
+(define-class <my-class2> (<object>)
+   slot @dots{}
+   #:metaclass <my-metaclass>)
+@end example
+
+@noindent
+and Guile expands @emph{this} to something like:
+
+@example
+(define <my-class2>
+  (make <my-metaclass> #:dsupers (list <object>) #:slots slots))
+@end example
+
+In this case, the value of @code{<my-class2>} is an instance of the more
+specialized class @code{<my-metaclass>}.  Note that
+@code{<my-metaclass>} itself must previously have been defined as a
+subclass of @code{<class>}.  For a full discussion of when and how it is
+useful to define new metaclasses, see @ref{MOP Specification}.
+
+Now let's make an instance of @code{<my-class2>}:
+
+@example
+(define my-object (make <my-class2> ...))
+@end example
+
+All of the following statements are correct expressions of the
+relationships between @code{my-object}, @code{<my-class2>},
+@code{<my-metaclass>} and @code{<class>}.
 
 @itemize @bullet
 @item
-What are the data members of this object or class?
+@code{my-object} is an instance of the class @code{<my-class2>}.
 
 @item
-What classes does this class inherit from?
+@code{<my-class2>} is an instance of the class @code{<my-metaclass>}.
 
 @item
-Is this method call virtual or non-virtual?
+@code{<my-metaclass>} is an instance of the class @code{<class>}.
 
 @item
-If I invoke @code{Employee::adjustHoliday()}, what class contains the
-@code{adjustHoliday()} method that will be applied?
-@end itemize
+The class of @code{my-object} is @code{<my-class2>}.
 
-In C++, answers to such questions can only be determined by looking at
-the source code, if you have access to it.  GOOPS, on the other hand,
-includes procedures that allow answers to these questions --- or their
-GOOPS equivalents --- to be obtained dynamically, at run time.
+@item
+The class of @code{<my-class2>} is @code{<my-metaclass>}.
 
-@menu
-* Classes::
-* Slots::
-* Instances::
-* Generic Functions::
-* Generic Function Methods::
-@end menu
+@item
+The class of @code{<my-metaclass>} is @code{<class>}.
+@end itemize
 
-@node Classes
-@subsubsection Classes
 
-@deffn {primitive procedure} class-name class
-Return the name of class @var{class}.
-This is the value of the @var{class} metaobject's @code{name} slot.
-@end deffn
+@node MOP Specification
+@subsection MOP Specification
 
-@deffn {primitive procedure} class-direct-supers class
-Return a list containing the direct superclasses of @var{class}.
-This is the value of the @var{class} metaobject's
-@code{direct-supers} slot.
-@end deffn
+The aim of the MOP specification in this chapter is to specify all the
+customizable generic function invocations that can be made by the standard
+GOOPS syntax, procedures and methods, and to explain the protocol for
+customizing such invocations.
 
-@deffn {primitive procedure} class-direct-slots class
-Return a list containing the slot definitions of the direct slots of
-@var{class}.
-This is the value of the @var{class} metaobject's @code{direct-slots}
-slot.
-@end deffn
+A generic function invocation is customizable if the types of the
+arguments to which it is applied are not completely determined by the
+lexical context in which the invocation appears.  For example, the
+@code{(initialize @var{instance} @var{initargs})} invocation in the
+default @code{make-instance} method is customizable, because the type of
+the @code{@var{instance}} argument is determined by the class that was
+passed to @code{make-instance}.
 
-@deffn {primitive procedure} class-direct-subclasses class
-Return a list containing the direct subclasses of @var{class}.
-This is the value of the @var{class} metaobject's
-@code{direct-subclasses} slot.
-@end deffn
+(Whereas --- to give a counter-example --- the @code{(make <generic>
+#:name ',name)} invocation in @code{define-generic} is not customizable,
+because all of its arguments have lexically determined types.)
 
-@deffn {primitive procedure} class-direct-methods class
-Return a list of all the generic function methods that use @var{class}
-as a formal parameter specializer.
-This is the value of the @var{class} metaobject's @code{direct-methods}
-slot.
-@end deffn
+When using this rule to decide whether a given generic function invocation
+is customizable, we ignore arguments that are expected to be handled in
+method definitions as a single ``rest'' list argument.
 
-@deffn {primitive procedure} class-precedence-list class
-Return the class precedence list for class @var{class} (@pxref{Class
-precedence list}).
-This is the value of the @var{class} metaobject's @code{cpl} slot.
-@end deffn
+For each customizable generic function invocation, the @dfn{invocation
+protocol} is explained by specifying
 
-@deffn {primitive procedure} class-slots class
-Return a list containing the slot definitions for all @var{class}'s slots,
-including any slots that are inherited from superclasses.
-This is the value of the @var{class} metaobject's @code{slots} slot.
-@end deffn
+@itemize @bullet
+@item
+what, conceptually, the applied method is intended to do
 
-@deffn {primitive procedure} class-environment class
-Return the value of @var{class}'s @code{environment} slot.
-[ *fixme*  I don't know what this value is used for. ]
-@end deffn
+@item
+what assumptions, if any, the caller makes about the applied method's side
+effects
 
-@deffn procedure class-subclasses class
-Return a list of all subclasses of @var{class}.
-@end deffn
+@item
+what the caller expects to get as the applied method's return value.
+@end itemize
 
-@deffn procedure class-methods class
-Return a list of all methods that use @var{class} or a subclass of
-@var{class} as one of its formal parameter specializers.
-@end deffn
 
-@node Slots
-@subsubsection Slots
+@node Instance Creation Protocol
+@subsection Instance Creation Protocol
 
-@deffn procedure class-slot-definition class slot-name
-Return the slot definition for the slot named @var{slot-name} in class
-@var{class}.  @var{slot-name} should be a symbol.
-@end deffn
+@code{make <class> . @var{initargs}} (method)
 
-@deffn procedure slot-definition-name slot-def
-Extract and return the slot name from @var{slot-def}.
-@end deffn
+@itemize @bullet
+@item
+@code{allocate-instance @var{class} @var{initargs}} (generic)
 
-@deffn procedure slot-definition-options slot-def
-Extract and return the slot options from @var{slot-def}.
-@end deffn
+The applied @code{allocate-instance} method should allocate storage for
+a new instance of class @var{class} and return the uninitialized instance.
 
-@deffn procedure slot-definition-allocation slot-def
-Extract and return the slot allocation option from @var{slot-def}.  This
-is the value of the @code{#:allocation} keyword (@pxref{Slot Options,,
-allocation}), or @code{#:instance} if the @code{#:allocation} keyword is
-absent.
-@end deffn
+@item
+@code{initialize @var{instance} @var{initargs}} (generic)
 
-@deffn procedure slot-definition-getter slot-def
-Extract and return the slot getter option from @var{slot-def}.  This is
-the value of the @code{#:getter} keyword (@pxref{Slot Options,,
-getter}), or @code{#f} if the @code{#:getter} keyword is absent.
-@end deffn
+@var{instance} is the uninitialized instance returned by
+@code{allocate-instance}.  The applied method should initialize the new
+instance in whatever sense is appropriate for its class.  The method's
+return value is ignored.
+@end itemize
 
-@deffn procedure slot-definition-setter slot-def
-Extract and return the slot setter option from @var{slot-def}.  This is
-the value of the @code{#:setter} keyword (@pxref{Slot Options,,
-setter}), or @code{#f} if the @code{#:setter} keyword is absent.
-@end deffn
+@code{make} itself is a generic function.  Hence the @code{make}
+invocation itself can be customized in the case where the new instance's
+metaclass is more specialized than the default @code{<class>}, by
+defining a @code{make} method that is specialized to that metaclass.
 
-@deffn procedure slot-definition-accessor slot-def
-Extract and return the slot accessor option from @var{slot-def}.  This
-is the value of the @code{#:accessor} keyword (@pxref{Slot Options,,
-accessor}), or @code{#f} if the @code{#:accessor} keyword is absent.
-@end deffn
+Normally, however, the method for classes with metaclass @code{<class>}
+will be applied.  This method calls two generic functions:
 
-@deffn procedure slot-definition-init-value slot-def
-Extract and return the slot init-value option from @var{slot-def}.  This
-is the value of the @code{#:init-value} keyword (@pxref{Slot Options,,
-init-value}), or the unbound value if the @code{#:init-value} keyword is
-absent.
+@itemize @bullet
+@item
+(allocate-instance @var{class} . @var{initargs})
+
+@item
+(initialize @var{instance} . @var{initargs})
+@end itemize
+
+@code{allocate-instance} allocates storage for and returns the new
+instance, uninitialized.  You might customize @code{allocate-instance},
+for example, if you wanted to provide a GOOPS wrapper around some other
+object programming system.
+
+To do this, you would create a specialized metaclass, which would act as
+the metaclass for all classes and instances from the other system.  Then
+define an @code{allocate-instance} method, specialized to that
+metaclass, which calls a Guile primitive C function (or FFI code), which
+in turn allocates the new instance using the interface of the other
+object system.
+
+In this case, for a complete system, you would also need to customize a
+number of other generic functions like @code{make} and
+@code{initialize}, so that GOOPS knows how to make classes from the
+other system, access instance slots, and so on.
+
+@code{initialize} initializes the instance that is returned by
+@code{allocate-instance}.  The standard GOOPS methods perform
+initializations appropriate to the instance class.
+
+@itemize @bullet
+@item
+At the least specialized level, the method for instances of type
+@code{<object>} performs internal GOOPS instance initialization, and
+initializes the instance's slots according to the slot definitions and
+any slot initialization keywords that appear in @var{initargs}.
+
+@item
+The method for instances of type @code{<class>} calls
+@code{(next-method)}, then performs the class initializations described
+in @ref{Class Definition Protocol}.
+
+@item
+and so on for generic functions, methods, operator classes @dots{}
+@end itemize
+
+Similarly, you can customize the initialization of instances of any
+application-defined class by defining an @code{initialize} method
+specialized to that class.
+
+Imagine a class whose instances' slots need to be initialized at
+instance creation time by querying a database.  Although it might be
+possible to achieve this a combination of @code{#:init-thunk} keywords
+and closures in the slot definitions, it may be neater to write an
+@code{initialize} method for the class that queries the database once
+and initializes all the dependent slot values according to the results.
+
+
+@node Class Definition Protocol
+@subsection Class Definition Protocol
+
+Here is a summary diagram of the syntax, procedures and generic
+functions that may be involved in class definition.
+
+@noindent
+@code{define-class} (syntax)
+
+@itemize @bullet
+@item
+@code{class} (syntax)
+
+@itemize @bullet
+@item
+@code{make-class} (procedure)
+
+@itemize @bullet
+@item
+@code{ensure-metaclass} (procedure)
+
+@item
+@code{make @var{metaclass} @dots{}} (generic)
+
+@itemize @bullet
+@item
+@code{allocate-instance} (generic)
+
+@item
+@code{initialize} (generic)
+
+@itemize @bullet
+@item
+@code{compute-cpl} (generic)
+
+@itemize @bullet
+@item
+@code{compute-std-cpl} (procedure)
+@end itemize
+
+@item
+@code{compute-slots} (generic)
+
+@item
+@code{compute-get-n-set} (generic)
+
+@item
+@code{compute-getter-method} (generic)
+
+@item
+@code{compute-setter-method} (generic)
+@end itemize
+@end itemize
+@end itemize
+@end itemize
+
+@item
+@code{class-redefinition} (generic)
+
+@itemize @bullet
+@item
+@code{remove-class-accessors} (generic)
+
+@item
+@code{update-direct-method!} (generic)
+
+@item
+@code{update-direct-subclass!} (generic)
+@end itemize
+@end itemize
+
+Wherever a step above is marked as ``generic'', it can be customized,
+and the detail shown below it is only ``correct'' insofar as it
+describes what the default method of that generic function does.  For
+example, if you write an @code{initialize} method, for some metaclass,
+that does not call @code{next-method} and does not call
+@code{compute-cpl}, then @code{compute-cpl} will not be called when a
+class is defined with that metaclass. 
+
+A @code{(define-class ...)} form (@pxref{Class Definition}) expands to
+an expression which
+
+@itemize @bullet
+@item
+checks that it is being evaluated only at top level
+
+@item
+defines any accessors that are implied by the @var{slot-definition}s
+
+@item
+uses @code{class} to create the new class
+
+@item
+checks for a previous class definition for @var{name} and, if found,
+handles the redefinition by invoking @code{class-redefinition}
+(@pxref{Redefining a Class}).
+@end itemize
+
+@deffn syntax class name (super @dots{}) @
+              slot-definition @dots{} class-option @dots{}
+Return a newly created class that inherits from @var{super}s, with
+direct slots defined by @var{slot-definition}s and @var{class-option}s.
+For the format of @var{slot-definition}s and @var{class-option}s, see
+@ref{Class Definition,, define-class}.
 @end deffn
 
-@deffn procedure slot-definition-init-form slot-def
-Extract and return the slot init-form option from @var{slot-def}.  This
-is the value of the @code{#:init-form} keyword (@pxref{Slot Options,,
-init-form}), or the unbound value if the @code{#:init-form} keyword is
-absent.
+@noindent @code{class} expands to an expression which
+
+@itemize @bullet
+@item
+processes the class and slot definition options to check that they are
+well-formed, to convert the @code{#:init-form} option to an
+@code{#:init-thunk} option, to supply a default environment parameter
+(the current top-level environment) and to evaluate all the bits that
+need to be evaluated
+
+@item
+calls @code{make-class} to create the class with the processed and
+evaluated parameters.
+@end itemize
+
+@deffn procedure make-class supers slots class-option @dots{}
+Return a newly created class that inherits from @var{supers}, with
+direct slots defined by @var{slots} and @var{class-option}s.  For the
+format of @var{slots} and @var{class-option}s, see @ref{Class
+Definition,, define-class}, except note that for @code{make-class},
+@var{slots} is a separate list of slot definitions.
 @end deffn
 
-@deffn procedure slot-definition-init-thunk slot-def
-Extract and return the slot init-thunk option from @var{slot-def}.  This
-is the value of the @code{#:init-thunk} keyword (@pxref{Slot Options,,
-init-thunk}), or @code{#f} if the @code{#:init-thunk} keyword is absent.
+@noindent @code{make-class}
+
+@itemize @bullet
+@item
+adds @code{<object>} to the @var{supers} list if @var{supers} is empty
+or if none of the classes in @var{supers} have @code{<object>} in their
+class precedence list
+
+@item
+defaults the @code{#:environment}, @code{#:name} and @code{#:metaclass}
+options, if they are not specified by @var{options}, to the current
+top-level environment, the unbound value, and @code{(ensure-metaclass
+@var{supers})} respectively
+
+@item
+checks for duplicate classes in @var{supers} and duplicate slot names in
+@var{slots}, and signals an error if there are any duplicates
+
+@item
+calls @code{make}, passing the metaclass as the first parameter and all
+other parameters as option keywords with values.
+@end itemize
+
+@deffn procedure ensure-metaclass supers env
+Return a metaclass suitable for a class that inherits from the list of
+classes in @var{supers}.  The returned metaclass is the union by
+inheritance of the metaclasses of the classes in @var{supers}.
+
+In the simplest case, where all the @var{supers} are straightforward
+classes with metaclass @code{<class>}, the returned metaclass is just
+@code{<class>}.
+
+For a more complex example, suppose that @var{supers} contained one
+class with metaclass @code{<operator-class>} and one with metaclass
+@code{<foreign-object-class>}.  Then the returned metaclass would be a
+class that inherits from both @code{<operator-class>} and
+@code{<foreign-object-class>}.
+
+If @var{supers} is the empty list, @code{ensure-metaclass} returns the
+default GOOPS metaclass @code{<class>}.
+
+GOOPS keeps a list of the metaclasses created by
+@code{ensure-metaclass}, so that each required type of metaclass only
+has to be created once.
+
+The @code{env} parameter is ignored.
 @end deffn
 
-@deffn procedure slot-definition-init-keyword slot-def
-Extract and return the slot init-keyword option from @var{slot-def}.
-This is the value of the @code{#:init-keyword} keyword (@pxref{Slot
-Options,, init-keyword}), or @code{#f} if the @code{#:init-keyword}
-keyword is absent.
+@deffn generic make metaclass initarg @dots{}
+@var{metaclass} is the metaclass of the class being defined, either
+taken from the @code{#:metaclass} class option or computed by
+@code{ensure-metaclass}.  The applied method must create and return the
+fully initialized class metaobject for the new class definition.
 @end deffn
 
-@deffn procedure slot-init-function class slot-name
-Return the initialization function for the slot named @var{slot-name} in
-class @var{class}.  @var{slot-name} should be a symbol.
+The @code{(make @var{metaclass} @var{initarg} @dots{})} invocation is a
+particular case of the instance creation protocol covered in the
+previous section.  It will create an class metaobject with metaclass
+@var{metaclass}.  By default, this metaobject will be initialized by the
+@code{initialize} method that is specialized for instances of type
+@code{<class>}.
 
-The returned initialization function incorporates the effects of the
-standard @code{#:init-thunk}, @code{#:init-form} and @code{#:init-value}
-slot options.  These initializations can be overridden by the
-@code{#:init-keyword} slot option or by a specialized @code{initialize}
-method, so, in general, the function returned by
-@code{slot-init-function} may be irrelevant.  For a fuller discussion,
-see @ref{Slot Options,, init-value}.
-@end deffn
+The @code{initialize} method for classes (signature @code{(initialize
+<class> initargs)}) calls the following generic functions.
 
-@node Instances
-@subsubsection Instances
+@itemize @bullet
+@item
+@code{compute-cpl @var{class}} (generic)
 
-@deffn {primitive procedure} class-of value
-Return the GOOPS class of any Scheme @var{value}.
+The applied method should compute and return the class precedence list
+for @var{class} as a list of class metaobjects.  When @code{compute-cpl}
+is called, the following @var{class} metaobject slots have all been
+initialized: @code{name}, @code{direct-supers}, @code{direct-slots},
+@code{direct-subclasses} (empty), @code{direct-methods}.  The value
+returned by @code{compute-cpl} will be stored in the @code{cpl} slot.
+
+@item
+@code{compute-slots @var{class}} (generic)
+
+The applied method should compute and return the slots (union of direct
+and inherited) for @var{class} as a list of slot definitions.  When
+@code{compute-slots} is called, all the @var{class} metaobject slots
+mentioned for @code{compute-cpl} have been initialized, plus the
+following: @code{cpl}, @code{redefined} (@code{#f}), @code{environment}.
+The value returned by @code{compute-slots} will be stored in the
+@code{slots} slot.
+
+@item
+@code{compute-get-n-set @var{class} @var{slot-def}} (generic)
+
+@code{initialize} calls @code{compute-get-n-set} for each slot computed
+by @code{compute-slots}.  The applied method should compute and return a
+pair of closures that, respectively, get and set the value of the specified
+slot.  The get closure should have arity 1 and expect a single argument
+that is the instance whose slot value is to be retrieved.  The set closure
+should have arity 2 and expect two arguments, where the first argument is
+the instance whose slot value is to be set and the second argument is the
+new value for that slot.  The closures should be returned in a two element
+list: @code{(list @var{get} @var{set})}.
+
+The closures returned by @code{compute-get-n-set} are stored as part of
+the value of the @var{class} metaobject's @code{getters-n-setters} slot.
+Specifically, the value of this slot is a list with the same number of
+elements as there are slots in the class, and each element looks either like
+
+@example
+@code{(@var{slot-name-symbol} @var{init-function} . @var{index})}
+@end example
+
+or like
+
+@example
+@code{(@var{slot-name-symbol} @var{init-function} @var{get} @var{set})}
+@end example
+
+Where the get and set closures are replaced by @var{index}, the slot is
+an instance slot and @var{index} is the slot's index in the underlying
+structure: GOOPS knows how to get and set the value of such slots and so
+does not need specially constructed get and set closures.  Otherwise,
+@var{get} and @var{set} are the closures returned by @code{compute-get-n-set}.
+
+The structure of the @code{getters-n-setters} slot value is important when
+understanding the next customizable generic functions that @code{initialize}
+calls@dots{}
+
+@item
+@code{compute-getter-method @var{class} @var{gns}} (generic)
+
+@code{initialize} calls @code{compute-getter-method} for each of the
+class's slots (as determined by @code{compute-slots}) that includes a
+@code{#:getter} or @code{#:accessor} slot option.  @var{gns} is the
+element of the @var{class} metaobject's @code{getters-n-setters} slot
+that specifies how the slot in question is referenced and set, as
+described above under @code{compute-get-n-set}.  The applied method
+should create and return a method that is specialized for instances of
+type @var{class} and uses the get closure to retrieve the slot's value.
+@code{initialize} uses @code{add-method!} to add the returned method to
+the generic function named by the slot definition's @code{#:getter} or
+@code{#:accessor} option.
+
+@item
+@code{compute-setter-method @var{class} @var{gns}} (generic)
+
+@code{compute-setter-method} is invoked with the same arguments as
+@code{compute-getter-method}, for each of the class's slots that includes
+a @code{#:setter} or @code{#:accessor} slot option.  The applied method
+should create and return a method that is specialized for instances of
+type @var{class} and uses the set closure to set the slot's value.
+@code{initialize} then uses @code{add-method!} to add the returned method
+to the generic function named by the slot definition's @code{#:setter}
+or @code{#:accessor} option.
+@end itemize
+
+@node Customizing Class Definition
+@subsection Customizing Class Definition
+
+If the metaclass of the new class is something more specialized than the
+default @code{<class>}, then the type of @var{class} in the calls above
+is more specialized than @code{<class>}, and hence it becomes possible
+to define generic function methods, specialized for the new class's
+metaclass, that can modify or override the default behaviour of
+@code{initialize}, @code{compute-cpl} or @code{compute-get-n-set}.
+
+@code{compute-cpl} computes the class precedence list (``CPL'') for the
+new class (@pxref{Class Precedence List}), and returns it as a list of
+class objects.  The CPL is important because it defines a superclass
+ordering that is used, when a generic function is invoked upon an
+instance of the class, to decide which of the available generic function
+methods is the most specific.  Hence @code{compute-cpl} could be
+customized in order to modify the CPL ordering algorithm for all classes
+with a special metaclass.
+
+The default CPL algorithm is encapsulated by the @code{compute-std-cpl}
+procedure, which is called by the default @code{compute-cpl} method.
+
+@deffn procedure compute-std-cpl class
+Compute and return the class precedence list for @var{class} according
+to the algorithm described in @ref{Class Precedence List}.
 @end deffn
 
-@deffn {primitive procedure} instance? object
-Return @code{#t} if @var{object} is any GOOPS instance, otherwise
-@code{#f}.
-@end deffn
+@code{compute-slots} computes and returns a list of all slot definitions
+for the new class.  By default, this list includes the direct slot
+definitions from the @code{define-class} form, plus the slot definitions
+that are inherited from the new class's superclasses.  The default
+@code{compute-slots} method uses the CPL computed by @code{compute-cpl}
+to calculate this union of slot definitions, with the rule that slots
+inherited from superclasses are shadowed by direct slots with the same
+name.  One possible reason for customizing @code{compute-slots} would be
+to implement an alternative resolution strategy for slot name conflicts.
+
+@code{compute-get-n-set} computes the low-level closures that will be
+used to get and set the value of a particular slot, and returns them in
+a list with two elements.
+
+The closures returned depend on how storage for that slot is allocated.
+The standard @code{compute-get-n-set} method, specialized for classes of
+type @code{<class>}, handles the standard GOOPS values for the
+@code{#:allocation} slot option (@pxref{Slot Options,, allocation}).  By
+defining a new @code{compute-get-n-set} method for a more specialized
+metaclass, it is possible to support new types of slot allocation.
+
+Suppose you wanted to create a large number of instances of some class
+with a slot that should be shared between some but not all instances of
+that class - say every 10 instances should share the same slot storage.
+The following example shows how to implement and use a new type of slot
+allocation to do this.
+
+@example
+(define-class <batched-allocation-metaclass> (<class>))
+
+(let ((batch-allocation-count 0)
+      (batch-get-n-set #f))
+  (define-method (compute-get-n-set
+                     (class <batched-allocation-metaclass>) s)
+    (case (slot-definition-allocation s)
+      ((#:batched)
+       ;; If we've already used the same slot storage for 10 instances,
+       ;; reset variables.
+       (if (= batch-allocation-count 10)
+           (begin
+             (set! batch-allocation-count 0)
+             (set! batch-get-n-set #f)))
+       ;; If we don't have a current pair of get and set closures,
+       ;; create one.  make-closure-variable returns a pair of closures
+       ;; around a single Scheme variable - see goops.scm for details.
+       (or batch-get-n-set
+           (set! batch-get-n-set (make-closure-variable)))
+       ;; Increment the batch allocation count.
+       (set! batch-allocation-count (+ batch-allocation-count 1))
+       batch-get-n-set)
+
+      ;; Call next-method to handle standard allocation types.
+      (else (next-method)))))
+
+(define-class <class-using-batched-slot> ()
+  ...
+  (c #:allocation #:batched)
+  ...
+  #:metaclass <batched-allocation-metaclass>)
+@end example
+
+The usage of @code{compute-getter-method} and @code{compute-setter-method}
+is described in @ref{Class Definition Protocol}.
 
-@deffn procedure is-a? object class
-Return @code{#t} if @var{object} is an instance of @var{class} or one of
-its subclasses.
-@end deffn
+@code{compute-cpl} and @code{compute-get-n-set} are called by the
+standard @code{initialize} method for classes whose metaclass is
+@code{<class>}.  But @code{initialize} itself can also be modified, by
+defining an @code{initialize} method specialized to the new class's
+metaclass.  Such a method could complete override the standard
+behaviour, by not calling @code{(next-method)} at all, but more
+typically it would perform additional class initialization steps before
+and/or after calling @code{(next-method)} for the standard behaviour.
 
-Implementation notes: @code{is-a?} uses @code{class-of} and
-@code{class-precedence-list} to obtain the class precedence list for
-@var{object}.
 
-@node Generic Functions
-@subsubsection Generic Functions
+@node Method Definition
+@subsection Method Definition
 
-@deffn {primitive procedure} generic-function-name gf
-Return the name of generic function @var{gf}.
-@end deffn
+@code{define-method} (syntax)
 
-@deffn {primitive procedure} generic-function-methods gf
-Return a list of the methods of generic function @var{gf}.
-This is the value of the @var{gf} metaobject's @code{methods} slot.
-@end deffn
+@itemize @bullet
+@item
+@code{add-method! @var{target} @var{method}} (generic)
+@end itemize
 
-@node Generic Function Methods
-@subsubsection Generic Function Methods
+@noindent
+@code{define-method} invokes the @code{add-method!} generic function to
+handle adding the new method to a variety of possible targets.  GOOPS
+includes methods to handle @var{target} as
 
-@deffn {primitive procedure} method-generic-function method
-Return the generic function that @var{method} belongs to.
-This is the value of the @var{method} metaobject's
-@code{generic-function} slot.
-@end deffn
+@itemize @bullet
+@item
+a generic function (the most common case)
 
-@deffn {primitive procedure} method-specializers method
-Return a list of @var{method}'s formal parameter specializers .
-This is the value of the @var{method} metaobject's
-@code{specializers} slot.
-@end deffn
+@item
+a procedure
 
-@deffn {primitive procedure} method-procedure method
-Return the procedure that implements @var{method}.
-This is the value of the @var{method} metaobject's
-@code{procedure} slot.
-@end deffn
+@item
+a primitive generic (@pxref{Extending Primitives})
+@end itemize
 
-@deffn generic method-source
-@deffnx method method-source (m <method>)
-Return an expression that prints to show the definition of method
-@var{m}.
+By defining further methods for @code{add-method!}, you can
+theoretically handle adding methods to further types of target.
 
-@example
-(define-generic cube)
 
-(define-method (cube (n <number>))
-  (* n n n))
+@node Method Definition Internals
+@subsection Method Definition Internals
 
-(map method-source (generic-function-methods cube))
-@result{}
-((method ((n <number>)) (* n n n)))
-@end example
-@end deffn
+@code{define-method}:
 
-@node Miscellaneous Functions
-@subsection Miscellaneous Functions
+@itemize @bullet
+@item
+checks the form of the first parameter, and applies the following steps
+to the accessor's setter if it has the @code{(setter @dots{})} form
 
-@menu
-* Administrative Functions::
-* GOOPS Error Handling::
-* Object Comparisons::
-* Cloning Objects::
-* Write and Display::
-@end menu
+@item
+interpolates a call to @code{define-generic} or @code{define-accessor}
+if a generic function is not already defined with the supplied name
+
+@item
+calls @code{method} with the @var{parameter}s and @var{body}, to make a
+new method instance
 
-@node Administrative Functions
-@subsubsection Administration Functions
+@item
+calls @code{add-method!} to add this method to the relevant generic
+function.
+@end itemize
 
-This section describes administrative, non-technical GOOPS functions.
+@deffn syntax method (parameter @dots{}) body @dots{}
+Make a method whose specializers are defined by the classes in
+@var{parameter}s and whose procedure definition is constructed from the
+@var{parameter} symbols and @var{body} forms.
 
-@deffn primitive goops-version
-Return the current GOOPS version as a string, for example ``0.2''.
+The @var{parameter} and @var{body} parameters should be as for
+@code{define-method} (@pxref{Methods and Generic Functions,,
+define-method}).
 @end deffn
 
-@node GOOPS Error Handling
-@subsubsection Error Handling
-
-The procedure @code{goops-error} is called to raise an appropriate error
-by the default methods of the following generic functions:
+@noindent
+@code{method}:
 
 @itemize @bullet
 @item
-@code{slot-missing} (@pxref{Handling Slot Access Errors,, slot-missing})
+extracts formals and specializing classes from the @var{parameter}s,
+defaulting the class for unspecialized parameters to @code{<top>}
 
 @item
-@code{slot-unbound} (@pxref{Handling Slot Access Errors,, slot-unbound})
+creates a closure using the formals and the @var{body} forms
 
 @item
-@code{no-method} (@pxref{Handling Invocation Errors,, no-method})
+calls @code{make} with metaclass @code{<method>} and the specializers
+and closure using the @code{#:specializers} and @code{#:procedure}
+keywords.
+@end itemize
 
-@item
-@code{no-applicable-method} (@pxref{Handling Invocation Errors,,
-no-applicable-method})
+@deffn procedure make-method specializers procedure
+Make a method using @var{specializers} and @var{procedure}.
 
-@item
-@code{no-next-method} (@pxref{Handling Invocation Errors,,
-no-next-method})
-@end itemize
+@var{specializers} should be a list of classes that specifies the
+parameter combinations to which this method will be applicable.
 
-If you customize these functions for particular classes or metaclasses,
-you may still want to use @code{goops-error} to signal any error
-conditions that you detect.
+@var{procedure} should be the closure that will applied to the generic
+function parameters when this method is invoked.
+@end deffn
 
-@deffn procedure goops-error format-string . args
-Raise an error with key @code{goops-error} and error message constructed
-from @var{format-string} and @var{args}.  Error message formatting is
-as done by @code{scm-error}.
-@end deffn
-
-@node Object Comparisons
-@subsubsection Object Comparisons
-
-@deffn generic eqv?
-@deffnx method eqv? ((x <top>) (y <top>))
-@deffnx generic equal?
-@deffnx method equal? ((x <top>) (y <top>))
-@deffnx generic =
-@deffnx method = ((x <number>) (y <number>))
-Generic functions and default (unspecialized) methods for comparing two
-GOOPS objects.
-
-The default method for @code{eqv?} returns @code{#t} for all values
-that are equal in the sense defined by R5RS and the Guile reference
-manual, otherwise @code{#f}.  The default method for @code{equal?}
-returns @code{#t} or @code{#f} in the sense defined by R5RS and the
-Guile reference manual.  If no such comparison is defined,
-@code{equal?} returns the result of a call to @code{eqv?}.  The
-default method for = returns @code{#t} if @var{x} and @var{y} are
-numerically equal, otherwise @code{#f}.
-
-Application class authors may wish to define specialized methods for
-@code{eqv?}, @code{equal?} and @code{=} that compare instances of the
-same class for equality in whatever sense is useful to the
-application.  Such methods will only be called if the arguments have
-the same class and the result of the comparison isn't defined by R5RS
-and the Guile reference manual.
-@end deffn
-
-@node Cloning Objects
-@subsubsection Cloning Objects
+@noindent
+@code{make-method} is a simple wrapper around @code{make} with metaclass
+@code{<method>}.
 
-@deffn generic shallow-clone
-@deffnx method shallow-clone (self <object>)
-Return a ``shallow'' clone of @var{self}.  The default method makes a
-shallow clone by allocating a new instance and copying slot values from
-self to the new instance.  Each slot value is copied either as an
-immediate value or by reference.
+@deffn generic add-method! target method
+Generic function for adding method @var{method} to @var{target}.
 @end deffn
 
-@deffn generic deep-clone
-@deffnx method deep-clone (self <object>)
-Return a ``deep'' clone of @var{self}.  The default method makes a deep
-clone by allocating a new instance and copying or cloning slot values
-from self to the new instance.  If a slot value is an instance
-(satisfies @code{instance?}), it is cloned by calling @code{deep-clone}
-on that value.  Other slot values are copied either as immediate values
-or by reference.
+@deffn method add-method! (generic <generic>) (method <method>)
+Add method @var{method} to the generic function @var{generic}.
 @end deffn
 
-@node Write and Display
-@subsubsection Write and Display
+@deffn method add-method! (proc <procedure>) (method <method>)
+If @var{proc} is a procedure with generic capability (@pxref{Extending
+Primitives,, generic-capability?}), upgrade it to a primitive generic
+and add @var{method} to its generic function definition.
+@end deffn
 
-@deffn {primitive generic} write object port
-@deffnx {primitive generic} display object port
-When GOOPS is loaded, @code{write} and @code{display} become generic
-functions with special methods for printing
+@deffn method add-method! (pg <primitive-generic>) (method <method>)
+Add method @var{method} to the generic function definition of @var{pg}.
 
-@itemize @bullet
-@item
-objects - instances of the class @code{<object>}
+Implementation: @code{(add-method! (primitive-generic-generic pg) method)}.
+@end deffn
 
-@item
-foreign objects - instances of the class @code{<foreign-object>}
+@deffn method add-method! (whatever <top>) (method <method>)
+Raise an error indicating that @var{whatever} is not a valid generic
+function.
+@end deffn
 
-@item
-classes - instances of the class @code{<class>}
+@node Generic Function Internals
+@subsection Generic Function Internals
 
-@item
-generic functions - instances of the class @code{<generic>}
+@code{define-generic} calls @code{ensure-generic} to upgrade a
+pre-existing procedure value, or @code{make} with metaclass
+@code{<generic>} to create a new generic function.
 
-@item
-methods - instances of the class @code{<method>}.
-@end itemize
+@code{define-accessor} calls @code{ensure-accessor} to upgrade a
+pre-existing procedure value, or @code{make-accessor} to create a new
+accessor.
 
-@code{write} and @code{display} print non-GOOPS values in the same way
-as the Guile primitive @code{write} and @code{display} functions.
-@end deffn
+@deffn procedure ensure-generic old-definition [name]
+Return a generic function with name @var{name}, if possible by using or
+upgrading @var{old-definition}.  If unspecified, @var{name} defaults to
+@code{#f}.
 
-@node MOP Specification
-@section MOP Specification
+If @var{old-definition} is already a generic function, it is returned
+unchanged.
 
-For an introduction to metaobjects and the metaobject protocol,
-see @ref{Metaobjects and the Metaobject Protocol}.
+If @var{old-definition} is a Scheme procedure or procedure-with-setter,
+@code{ensure-generic} returns a new generic function that uses
+@var{old-definition} for its default procedure and setter.
 
-The aim of the MOP specification in this chapter is to specify all the
-customizable generic function invocations that can be made by the standard
-GOOPS syntax, procedures and methods, and to explain the protocol for
-customizing such invocations.
+Otherwise @code{ensure-generic} returns a new generic function with no
+defaults and no methods.
+@end deffn
 
-A generic function invocation is customizable if the types of the arguments
-to which it is applied are not all determined by the lexical context in
-which the invocation appears.  For example,
+@deffn procedure make-generic [name]
+Return a new generic function with name @code{(car @var{name})}.  If
+unspecified, @var{name} defaults to @code{#f}.
+@end deffn
 
-@itemize @bullet
-@item
-the @code{(initialize @var{instance} @var{initargs})} invocation in the
-default @code{make-instance} method is customizable, because the type of the
-@code{@var{instance}} argument is determined by the class that was passed to
-@code{make-instance}.
+@code{ensure-generic} calls @code{make} with metaclasses
+@code{<generic>} and @code{<generic-with-setter>}, depending on the
+previous value of the variable that it is trying to upgrade.
 
-@item
-the @code{(make <generic> #:name ',name)} invocation in @code{define-generic}
-is not customizable, because all of its arguments have lexically determined
-types.
-@end itemize
+@code{make-generic} is a simple wrapper for @code{make} with metaclass
+@code{<generic>}.
 
-When using this rule to decide whether a given generic function invocation
-is customizable, we ignore arguments that are expected to be handled in
-method definitions as a single ``rest'' list argument.
+@deffn procedure ensure-accessor proc [name]
+Return an accessor with name @var{name}, if possible by using or
+upgrading @var{proc}.  If unspecified, @var{name} defaults to @code{#f}.
 
-For each customizable generic function invocation, the @dfn{invocation
-protocol} is explained by specifying
+If @var{proc} is already an accessor, it is returned unchanged.
 
-@itemize @bullet
-@item
-what, conceptually, the applied method is intended to do
+If @var{proc} is a Scheme procedure, procedure-with-setter or generic
+function, @code{ensure-accessor} returns an accessor that reuses the
+reusable elements of @var{proc}.
 
-@item
-what assumptions, if any, the caller makes about the applied method's side
-effects
+Otherwise @code{ensure-accessor} returns a new accessor with no defaults
+and no methods.
+@end deffn
 
-@item
-what the caller expects to get as the applied method's return value.
-@end itemize
+@deffn procedure make-accessor [name]
+Return a new accessor with name @code{(car @var{name})}.  If
+unspecified, @var{name} defaults to @code{#f}.
+@end deffn
 
-@menu
-* Class Definition::
-* Instance Creation::
-* Class Redefinition::
-* Method Definition::
-* Generic Function Invocation::
-@end menu
+@code{ensure-accessor} calls @code{make} with
+metaclass @code{<generic-with-setter>}, as well as calls to
+@code{ensure-generic}, @code{make-accessor} and (tail recursively)
+@code{ensure-accessor}.
 
-@node Class Definition
-@subsection Class Definition
+@code{make-accessor} calls @code{make} twice, first
+with metaclass @code{<generic>} to create a generic function for the
+setter, then with metaclass @code{<generic-with-setter>} to create the
+accessor, passing the setter generic function as the value of the
+@code{#:setter} keyword.
 
-@code{define-class} (syntax)
+@node Generic Function Invocation
+@subsection Generic Function Invocation
 
-@itemize @bullet
-@item
-@code{class} (syntax)
+There is a detailed and customizable protocol involved in the process of
+invoking a generic function --- i.e., in the process of deciding which
+of the generic function's methods are applicable to the current
+arguments, and which one of those to apply.  Here is a summary diagram
+of the generic functions involved.
+
+@noindent
+@code{apply-generic} (generic)
 
 @itemize @bullet
 @item
-@code{make-class} (procedure)
+@code{no-method} (generic)
 
-@itemize @bullet
 @item
-@code{make @var{metaclass} @dots{}} (generic)
-
-@var{metaclass} is the metaclass of the class being defined, either
-taken from the @code{#:metaclass} class option or computed by
-@code{ensure-metaclass}.  The applied method must create and return the
-fully initialized class metaobject for the new class definition.
-@end itemize
-
-@end itemize
+@code{compute-applicable-methods} (generic)
 
 @item
-@code{class-redefinition @var{old-class} @var{new-class}} (generic)
+@code{sort-applicable-methods} (generic)
 
-@code{define-class} calls @code{class-redefinition} if the variable
-specified by its first argument already held a GOOPS class definition.
-@var{old-class} and @var{new-class} are the old and new class metaobjects.
-The applied method should perform whatever is necessary to handle the
-redefinition, and should return the class metaobject that is to be bound
-to @code{define-class}'s variable.  The default class redefinition
-protocol is described in @ref{Class Redefinition}.
+@itemize @bullet
+@item
+@code{method-more-specific?} (generic)
 @end itemize
 
-The @code{(make @var{metaclass} @dots{})} invocation above will create
-an class metaobject with metaclass @var{metaclass}.  By default, this
-metaobject will be initialized by the @code{initialize} method that is
-specialized for instances of type @code{<class>}.
-
-@code{initialize <class> @var{initargs}} (method)
+@item
+@code{apply-methods} (generic)
 
 @itemize @bullet
 @item
-@code{compute-cpl @var{class}} (generic)
-
-The applied method should compute and return the class precedence list
-for @var{class} as a list of class metaobjects.  When @code{compute-cpl}
-is called, the following @var{class} metaobject slots have all been
-initialized: @code{name}, @code{direct-supers}, @code{direct-slots},
-@code{direct-subclasses} (empty), @code{direct-methods}.  The value
-returned by @code{compute-cpl} will be stored in the @code{cpl} slot.
+@code{apply-method} (generic)
 
 @item
-@code{compute-slots @var{class}} (generic)
-
-The applied method should compute and return the slots (union of direct
-and inherited) for @var{class} as a list of slot definitions.  When
-@code{compute-slots} is called, all the @var{class} metaobject slots
-mentioned for @code{compute-cpl} have been initialized, plus the
-following: @code{cpl}, @code{redefined} (@code{#f}), @code{environment}.
-The value returned by @code{compute-slots} will be stored in the
-@code{slots} slot.
+@code{no-next-method} (generic)
+@end itemize
 
 @item
-@code{compute-get-n-set @var{class} @var{slot-def}} (generic)
+@code{no-applicable-method}
+@end itemize
 
-@code{initialize} calls @code{compute-get-n-set} for each slot computed
-by @code{compute-slots}.  The applied method should compute and return a
-pair of closures that, respectively, get and set the value of the specified
-slot.  The get closure should have arity 1 and expect a single argument
-that is the instance whose slot value is to be retrieved.  The set closure
-should have arity 2 and expect two arguments, where the first argument is
-the instance whose slot value is to be set and the second argument is the
-new value for that slot.  The closures should be returned in a two element
-list: @code{(list @var{get} @var{set})}.
+We do not yet have full documentation for these.  Please refer to the
+code (@file{oop/goops.scm}) for details.
 
-The closures returned by @code{compute-get-n-set} are stored as part of
-the value of the @var{class} metaobject's @code{getters-n-setters} slot.
-Specifically, the value of this slot is a list with the same number of
-elements as there are slots in the class, and each element looks either like
 
-@example
-@code{(@var{slot-name-symbol} @var{init-function} . @var{index})}
-@end example
+@node Redefining a Class
+@section Redefining a Class
 
-or like
+Suppose that a class @code{<my-class>} is defined using @code{define-class}
+(@pxref{Class Definition,, define-class}), with slots that have
+accessor functions, and that an application has created several instances
+of @code{<my-class>} using @code{make} (@pxref{Instance Creation,,
+make}).  What then happens if @code{<my-class>} is redefined by calling
+@code{define-class} again?
 
-@example
-@code{(@var{slot-name-symbol} @var{init-function} @var{get} @var{set})}
-@end example
+@menu
+* Default Class Redefinition Behaviour::
+* Customizing Class Redefinition::
+@end menu
 
-Where the get and set closures are replaced by @var{index}, the slot is
-an instance slot and @var{index} is the slot's index in the underlying
-structure: GOOPS knows how to get and set the value of such slots and so
-does not need specially constructed get and set closures.  Otherwise,
-@var{get} and @var{set} are the closures returned by @code{compute-get-n-set}.
+@node Default Class Redefinition Behaviour
+@subsection Default Class Redefinition Behaviour
 
-The structure of the @code{getters-n-setters} slot value is important when
-understanding the next customizable generic functions that @code{initialize}
-calls@dots{}
+GOOPS' default answer to this question is as follows.
 
+@itemize @bullet
 @item
-@code{compute-getter-method @var{class} @var{gns}} (generic)
-
-@code{initialize} calls @code{compute-getter-method} for each of the class's
-slots (as determined by @code{compute-slots}) that includes a
-@code{#:getter} or @code{#:accessor} slot option.  @var{gns} is the
-element of the @var{class} metaobject's @code{getters-n-setters} slot that
-specifies how the slot in question is referenced and set, as described
-above under @code{compute-get-n-set}.  The applied method should create
-and return a method that is specialized for instances of type @var{class}
-and uses the get closure to retrieve the slot's value.  [ *fixme  Need
-to insert something here about checking that the value is not unbound. ]
-@code{initialize} uses @code{add-method!} to add the returned method to
-the generic function named by the slot definition's @code{#:getter} or
-@code{#:accessor} option.
+All existing direct instances of @code{<my-class>} are converted to be
+instances of the new class.  This is achieved by preserving the values
+of slots that exist in both the old and new definitions, and
+initializing the values of new slots in the usual way (@pxref{Instance
+Creation,, make}).
 
 @item
-@code{compute-setter-method @var{class} @var{gns}} (generic)
+All existing subclasses of @code{<my-class>} are redefined, as though
+the @code{define-class} expressions that defined them were re-evaluated
+following the redefinition of @code{<my-class>}, and the class
+redefinition process described here is applied recursively to the
+redefined subclasses.
 
-@code{compute-setter-method} is invoked with the same arguments as
-@code{compute-getter-method}, for each of the class's slots that includes
-a @code{#:setter} or @code{#:accessor} slot option.  The applied method
-should create and return a method that is specialized for instances of
-type @var{class} and uses the set closure to set the slot's value.
-@code{initialize} then uses @code{add-method!} to add the returned method
-to the generic function named by the slot definition's @code{#:setter}
-or @code{#:accessor} option.
+@item
+Once all of its instances and subclasses have been updated, the class
+metaobject previously bound to the variable @code{<my-class>} is no
+longer needed and so can be allowed to be garbage collected.
 @end itemize
 
-@node Instance Creation
-@subsection Instance Creation
-
-@code{make <class> . @var{initargs}} (method)
+To keep things tidy, GOOPS also needs to do a little housekeeping on
+methods that are associated with the redefined class.
 
 @itemize @bullet
 @item
-@code{allocate-instance @var{class} @var{initargs}} (generic)
-
-The applied @code{allocate-instance} method should allocate storage for
-a new instance of class @var{class} and return the uninitialized instance.
+Slot accessor methods for slots in the old definition should be removed
+from their generic functions.  They will be replaced by accessor methods
+for the slots of the new class definition.
 
 @item
-@code{initialize @var{instance} @var{initargs}} (generic)
-
-@var{instance} is the uninitialized instance returned by
-@code{allocate-instance}.  The applied method should initialize the new
-instance in whatever sense is appropriate for its class.  The method's
-return value is ignored.
+Any generic function method that uses the old @code{<my-class>} metaobject
+as one of its formal parameter specializers must be updated to refer to
+the new @code{<my-class>} metaobject.  (Whenever a new generic function
+method is defined, @code{define-method} adds the method to a list stored
+in the class metaobject for each class used as a formal parameter
+specializer, so it is easy to identify all the methods that must be
+updated when a class is redefined.)
 @end itemize
 
-@node Class Redefinition
-@subsection Class Redefinition
+If this class redefinition strategy strikes you as rather counter-intuitive,
+bear in mind that it is derived from similar behaviour in other object
+systems such as CLOS, and that experience in those systems has shown it to be
+very useful in practice.
 
-The default @code{class-redefinition} method, specialized for classes
-with the default metaclass @code{<class>}, has the following internal
-protocol.
+Also bear in mind that, like most of GOOPS' default behaviour, it can
+be customized@dots{}
 
-@code{class-redefinition (@var{old <class>}) (@var{new <class>})}
-(method)
+@node Customizing Class Redefinition
+@subsection Customizing Class Redefinition
 
-@itemize @bullet
-@item
-@code{remove-class-accessors! @var{old}} (generic)
+When @code{define-class} notices that a class is being redefined, it
+constructs the new class metaobject as usual, then invokes the
+@code{class-redefinition} generic function with the old and new classes
+as arguments.  Therefore, if the old or new classes have metaclasses
+other than the default @code{<class>}, class redefinition behaviour can
+be customized by defining a @code{class-redefinition} method that is
+specialized for the relevant metaclasses.
 
-@item
-@code{update-direct-method! @var{method} @var{old} @var{new}} (generic)
+@deffn generic class-redefinition
+Handle the class redefinition from @var{old-class} to @var{new-class},
+and return the new class metaobject that should be bound to the
+variable specified by @code{define-class}'s first argument.
+@end deffn
 
-@item
-@code{update-direct-subclass! @var{subclass} @var{old} @var{new}} (generic)
-@end itemize
+@deffn method class-redefinition (old-class <class>) (new-class <class>)
+Implements GOOPS' default class redefinition behaviour, as described in
+@ref{Default Class Redefinition Behaviour}.  Returns the metaobject
+for the new class definition.
+@end deffn
 
-This protocol cleans up things that the definition of the old class
-once changed and modifies things to work with the new class.
+The default @code{class-redefinition} method, for classes with the
+default metaclass @code{<class>}, calls the following generic functions,
+which could of course be individually customized.
 
-The default @code{remove-class-accessors!} method removes the
-accessor methods of the old class from all classes which they
-specialize.
+@deffn generic remove-class-accessors! old
+The default @code{remove-class-accessors!} method removes the accessor
+methods of the old class from all classes which they specialize.
+@end deffn
 
+@deffn generic update-direct-method! method old new
 The default @code{update-direct-method!} method substitutes the new
 class for the old in all methods specialized to the old class.
+@end deffn
 
+@deffn generic update-direct-subclass! subclass old new
 The default @code{update-direct-subclass!} method invokes
 @code{class-redefinition} recursively to handle the redefinition of
 subclasses.
+@end deffn
 
-When a class is redefined, any existing instance of the redefined class
-will be modified for the new class definition before the next time that
-any of the instance's slot is referenced or set.  GOOPS modifies each
-instance by calling the generic function @code{change-class}.
-
-The default @code{change-class} method copies slot values from the old
-to the modified instance, and initializes new slots, as described in
-@ref{Changing the Class of an Instance}.  After doing so, it makes a
-generic function invocation that can be used to customize the instance
-update algorithm.
-
-@code{change-class (@var{old-instance <object>}) (@var{new <class>})} (method)
-
-@itemize @bullet
-@item
-@code{update-instance-for-different-class @var{old-instance} @var{new-instance}} (generic)
-
-@code{change-class} invokes @code{update-instance-for-different-class}
-as the last thing that it does before returning.  The applied method can
-make any further adjustments to @var{new-instance} that are required to
-complete or modify the change of class.  The return value from the
-applied method is ignored.
-
-The default @code{update-instance-for-different-class} method does
-nothing.
-@end itemize
-
-@node Method Definition
-@subsection Method Definition
-
-@code{define-method} (syntax)
-
-@itemize @bullet
-@item
-@code{add-method! @var{target} @var{method}} (generic)
-
-@code{define-method} invokes the @code{add-method!} generic function to
-handle adding the new method to a variety of possible targets.  GOOPS
-includes methods to handle @var{target} as
-
-@itemize @bullet
-@item
-a generic function (the most common case)
-
-@item
-a procedure
+An alternative class redefinition strategy could be to leave all
+existing instances as instances of the old class, but accepting that the
+old class is now ``nameless'', since its name has been taken over by the
+new definition.  In this strategy, any existing subclasses could also
+be left as they are, on the understanding that they inherit from a nameless
+superclass.
 
-@item
-a primitive generic (@pxref{Extending Guiles Primitives})
-@end itemize
+This strategy is easily implemented in GOOPS, by defining a new metaclass,
+that will be used as the metaclass for all classes to which the strategy
+should apply, and then defining a @code{class-redefinition} method that
+is specialized for this metaclass:
 
-By defining further methods for @code{add-method!}, you can
-theoretically handle adding methods to further types of target.
-@end itemize
+@example
+(define-class <can-be-nameless> (<class>))
 
-@node Generic Function Invocation
-@subsection Generic Function Invocation
+(define-method (class-redefinition (old <can-be-nameless>)
+                                   (new <class>))
+  new)
+@end example
 
-[ *fixme* Description required here. ]
+When customization can be as easy as this, aren't you glad that GOOPS
+implements the far more difficult strategy as its default!
 
-@code{apply-generic}
 
-@itemize @bullet
-@item
-@code{no-method}
+@node Changing the Class of an Instance
+@section Changing the Class of an Instance
 
-@item
-@code{compute-applicable-methods}
+When a class is redefined, any existing instance of the redefined class
+will be modified for the new class definition before the next time that
+any of the instance's slots is referenced or set.  GOOPS modifies each
+instance by calling the generic function @code{change-class}.
 
-@item
-@code{sort-applicable-methods}
+More generally, you can change the class of an existing instance at any
+time by invoking the generic function @code{change-class} with two
+arguments: the instance and the new class.
 
-@item
-@code{apply-methods}
+The default method for @code{change-class} decides how to implement the
+change of class by looking at the slot definitions for the instance's
+existing class and for the new class.  If the new class has slots with
+the same name as slots in the existing class, the values for those slots
+are preserved.  Slots that are present only in the existing class are
+discarded.  Slots that are present only in the new class are initialized
+using the corresponding slot definition's init function (@pxref{Classes,,
+slot-init-function}).
 
-@item
-@code{no-applicable-method}
-@end itemize
+@deffn generic change-class instance new-class
+@end deffn
 
-@code{sort-applicable-methods}
+@deffn {method} change-class (obj <object>) (new <class>)
+Modify instance @var{obj} to make it an instance of class @var{new}.
 
-@itemize @bullet
-@item
-@code{method-more-specific?}
-@end itemize
+The value of each of @var{obj}'s slots is preserved only if a similarly named
+slot exists in @var{new}; any other slot values are discarded.
 
-@code{apply-methods}
+The slots in @var{new} that do not correspond to any of @var{obj}'s
+pre-existing slots are initialized according to @var{new}'s slot definitions'
+init functions.
+@end deffn
 
-@itemize @bullet
-@item
-@code{apply-method}
-@end itemize
+The default @code{change-class} method also invokes another generic
+function, @code{update-instance-for-different-class}, as the last thing
+that it does before returning.  The applied
+@code{update-instance-for-different-class} method can make any further
+adjustments to @var{new-instance} that are required to complete or
+modify the change of class.  The return value from the applied method is
+ignored.
 
-@code{next-method}
+@deffn generic update-instance-for-different-class old-instance new-instance
+A generic function that can be customized to put finishing touches to an
+instance whose class has just been changed.  The default
+@code{update-instance-for-different-class} method does nothing.
+@end deffn
 
-@itemize @bullet
-@item
-@code{no-next-method}
-@end itemize
+Customized change of class behaviour can be implemented by defining
+@code{change-class} methods that are specialized either by the class
+of the instances to be modified or by the metaclass of the new class.