This file documents GOOPS, an object oriented extension for Guile.

Copyright (C) 1999, 2000, 2001, 2003 Free Software Foundation

Permission is granted to make and distribute verbatim copies of this
manual provided the copyright notice and this permission notice are
preserved on all copies.

Class Slots
-----------

Slots whose allocation is per-class rather than per-instance can be
referenced and set without needing to specify any particular instance.

 - procedure: class-slot-ref class slot-name
     Return the value of the slot named SLOT-NAME in class CLASS.  The
     named slot must have `#:class' or `#:each-subclass' allocation
     (see allocation).

     If there is no such slot with `#:class' or `#:each-subclass'
     allocation, `class-slot-ref' calls the `slot-missing' generic
     function with arguments CLASS and SLOT-NAME.  Otherwise, if the
     slot value is unbound, `class-slot-ref' calls the `slot-missing'
     generic function, with the same arguments.

 - procedure: class-slot-set! class slot-name value
     Set the value of the slot named SLOT-NAME in class CLASS to VALUE.
     The named slot must have `#:class' or `#:each-subclass'
     allocation (see allocation).

     If there is no such slot with `#:class' or `#:each-subclass'
     allocation, `class-slot-ref' calls the `slot-missing' generic
     function with arguments CLASS and SLOT-NAME.

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.

 - generic: slot-missing
 - method: slot-missing (class <class>) slot-name
 - method: slot-missing (class <class>) (object <object>) slot-name
 - 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 CLASS or OBJECT, GOOPS calls the `slot-missing' generic
     function.

     The default methods all call `goops-error' with an appropriate
     message.

 - generic: slot-unbound
 - method: slot-unbound (object <object>)
 - method: slot-unbound (class <class>) slot-name
 - 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
     `slot-unbound' generic function.

     The default methods all call `goops-error' with an appropriate
     message.

Creating Generic Functions
==========================

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.

GOOPS represents generic functions as metaobjects of the class
`<generic>' (or one of its subclasses).

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 `define-generic' or
`define-accessor' before defining methods for the generic function
using `define-method', since `define-method' will automatically
interpolate a `define-generic' call, or upgrade an existing generic to
an accessor, if that is implied by the `define-method' call.  Note in
particular that, if the specified variable already has a _generic
function_ value, `define-generic' and `define-accessor' will _discard_
it!  Obviously it is application-dependent whether this is desirable or
not.

If, for example, you wanted to extend `+' for a class representing a
new numerical type, you probably want to inherit any existing methods
for `+' and so should not use `define-generic'.  If, on the other hand,
you do not want to risk inheriting methods whose behaviour might
surprise you, you can use `define-generic' or `define-accessor' to wipe
the slate clean.

 - syntax: define-generic symbol
     Create a generic function with name SYMBOL and bind it to the
     variable SYMBOL.

     If the variable 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 SYMBOL, including an existing generic function, is overwritten
     by the new generic function.

 - syntax: define-accessor symbol
     Create an accessor with name SYMBOL and bind it to the variable
     SYMBOL.

     If the variable 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 SYMBOL,
     including an existing generic function or accessor, is overwritten
     by the new definition.

Generic Function Internals
--------------------------

`define-generic' calls `ensure-generic' to upgrade a pre-existing
procedure value, or `make' with metaclass `<generic>' to create a new
generic function.

`define-accessor' calls `ensure-accessor' to upgrade a pre-existing
procedure value, or `make-accessor' to create a new accessor.

 - procedure: ensure-generic old-definition [name]
     Return a generic function with name NAME, if possible by using or
     upgrading OLD-DEFINITION.  If unspecified, NAME defaults to `#f'.

     If OLD-DEFINITION is already a generic function, it is returned
     unchanged.

     If OLD-DEFINITION is a Scheme procedure or procedure-with-setter,
     `ensure-generic' returns a new generic function that uses
     OLD-DEFINITION for its default procedure and setter.

     Otherwise `ensure-generic' returns a new generic function with no
     defaults and no methods.

 - procedure: make-generic [name]
     Return a new generic function with name `(car NAME)'.  If
     unspecified, NAME defaults to `#f'.

`ensure-generic' calls `make' with metaclasses `<generic>' and
`<generic-with-setter>', depending on the previous value of the
variable that it is trying to upgrade.

`make-generic' is a simple wrapper for `make' with metaclass
`<generic>'.

 - procedure: ensure-accessor proc [name]
     Return an accessor with name NAME, if possible by using or
     upgrading PROC.  If unspecified, NAME defaults to `#f'.

     If PROC is already an accessor, it is returned unchanged.

     If PROC is a Scheme procedure, procedure-with-setter or generic
     function, `ensure-accessor' returns an accessor that reuses the
     reusable elements of PROC.

     Otherwise `ensure-accessor' returns a new accessor with no defaults
     and no methods.

 - procedure: make-accessor [name]
     Return a new accessor with name `(car NAME)'.  If unspecified,
     NAME defaults to `#f'.

`ensure-accessor' calls `make' with metaclass `<generic-with-setter>',
as well as calls to `ensure-generic', `make-accessor' and (tail
recursively) `ensure-accessor'.

`make-accessor' calls `make' twice, first with metaclass `<generic>' to
create a generic function for the setter, then with metaclass
`<generic-with-setter>' to create the accessor, passing the setter
generic function as the value of the `#:setter' keyword.

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.

The `generic-capability?' predicate should be used to determine whether
a particular primitive is extensible in this way.

 - primitive procedure: generic-capability? primitive
     Return `#t' if PRIMITIVE can be extended by giving it a generic
     function definition, otherwise `#f'.

Even when a primitive procedure is extensible like this, its generic
function definition is not created until it is needed by a call to
`define-method', or until the application explicitly requests it by
calling `enable-primitive-generic!'.

 - primitive procedure: enable-primitive-generic! primitive
     Force the creation of a generic function definition for PRIMITIVE.

Once the generic function definition for a primitive has been created,
it can be retrieved using `primitive-generic-generic'.

 - primitive procedure: primitive-generic-generic primitive
     Return the generic function definition of PRIMITIVE.

     `primitive-generic-generic' raises an error if PRIMITIVE is not a
     primitive with generic capability, or if its generic capability
     has not yet been enabled, whether implicitly (by `define-method')
     or explicitly (by `enable-primitive-generic!').

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.

Adding Methods to Generic Functions
===================================

Basic Method Definition
-----------------------

To add a method to a generic function, use the `define-method' form.

 - syntax: define-method (generic parameter ...) . body
     Define a method for the generic function or accessor GENERIC with
     parameters PARAMETERs and body BODY.

     GENERIC is a generic function.  If GENERIC is a variable which is
     not yet bound to a generic function object, the expansion of
     `define-method' will include a call to `define-generic'.  If
     GENERIC is `(setter GENERIC-WITH-SETTER)', where
     GENERIC-WITH-SETTER is a variable which is not yet bound to a
     generic-with-setter object, the expansion will include a call to
     `define-accessor'.

     Each PARAMETER must be either a symbol or a two-element list
     `(SYMBOL CLASS)'.  The symbols refer to variables in the BODY that
     will be bound to the parameters supplied by the caller when
     calling this method.  The CLASSes, if present, specify the
     possible combinations of parameters to which this method can be
     applied.

     BODY is the body of the method definition.

`define-method' expressions look a little like normal Scheme procedure
definitions of the form

     (define (name formals ...) . body)

The most important difference is that each formal parameter, apart from
the possible "rest" argument, can be qualified by a class name:
`FORMAL' becomes `(FORMAL 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 `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.

Note that unqualified formal parameters act as though they are qualified
by the class `<top>', which GOOPS uses to mean the superclass of all
valid Scheme types, including both primitive types and GOOPS classes.

For example, if a generic function method is defined with PARAMETERs
`((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 `<square>' class and the second
parameter is a number.

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 Invoking Generic Functions.

Method Definition Internals
---------------------------

`define-method'

   * checks the form of the first parameter, and applies the following
     steps to the accessor's setter if it has the `(setter ...)' form

   * interpolates a call to `define-generic' or `define-accessor' if a
     generic function is not already defined with the supplied name

   * calls `method' with the PARAMETERs and BODY, to make a new method
     instance

   * calls `add-method!' to add this method to the relevant generic
     function.

 - syntax: method (parameter ...) . body
     Make a method whose specializers are defined by the classes in
     PARAMETERs and whose procedure definition is constructed from the
     PARAMETER symbols and BODY forms.

     The PARAMETER and BODY parameters should be as for `define-method'
     (see define-method).

`method'

   * extracts formals and specializing classes from the PARAMETERs,
     defaulting the class for unspecialized parameters to `<top>'

   * creates a closure using the formals and the BODY forms

   * calls `make' with metaclass `<method>' and the specializers and
     closure using the `#:specializers' and `#:procedure' keywords.

 - procedure: make-method specializers procedure
     Make a method using SPECIALIZERS and PROCEDURE.

     SPECIALIZERS should be a list of classes that specifies the
     parameter combinations to which this method will be applicable.

     PROCEDURE should be the closure that will applied to the generic
     function parameters when this method is invoked.

`make-method' is a simple wrapper around `make' with metaclass
`<method>'.

 - generic: add-method! target method
     Generic function for adding method METHOD to TARGET.

 - method: add-method! (generic <generic>) (method <method>)
     Add method METHOD to the generic function GENERIC.

 - method: add-method! (proc <procedure>) (method <method>)
     If PROC is a procedure with generic capability (see
     generic-capability?), upgrade it to a
     primitive generic and add METHOD to its generic function
     definition.

 - method: add-method! (pg <primitive-generic>) (method <method>)
     Add method METHOD to the generic function definition of PG.

     Implementation: `(add-method! (primitive-generic-generic pg)
     method)'.

 - method: add-method! (whatever <top>) (method <method>)
     Raise an error indicating that WHATEVER is not a valid generic
     function.

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? ]

Usually a generic function contains several method definitions, with
varying degrees of formal parameter specialization (see
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 `next-method'.

Determining Which Methods to Apply
----------------------------------

[ *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? ]

 - generic: apply-generic
 - method: apply-generic (gf <generic>) args

 - generic: compute-applicable-methods
 - method: compute-applicable-methods (gf <generic>) args

 - generic: sort-applicable-methods
 - method: sort-applicable-methods (gf <generic>) methods args

 - generic: method-more-specific?
 - method: method-more-specific? (m1 <method>) (m2 <method>) args

 - generic: apply-method
 - method: apply-method (gf <generic>) methods build-next args

 - generic: apply-methods
 - method: apply-methods (gf <generic>) (l <list>) args

Handling Invocation Errors
--------------------------

 - generic: no-method
 - 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
     `no-method' generic function.  The default method calls
     `goops-error' with an appropriate message.

 - generic: no-applicable-method
 - 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 `no-applicable-method' generic function.
     The default method calls `goops-error' with an appropriate message.

 - generic: no-next-method
 - method: no-next-method (gf <generic>) args
     When a generic function method calls `(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 `no-next-method' generic
     function.  The default method calls `goops-error' with an
     appropriate message.

Redefining a Class
==================

Suppose that a class `<my-class>' is defined using `define-class'
(see define-class), with slots that have
accessor functions, and that an application has created several
instances of `<my-class>' using `make' (see make).
What then happens if `<my-class>' is redefined by calling
`define-class' again?

Default Class Redefinition Behaviour
------------------------------------

GOOPS' default answer to this question is as follows.

   * All existing direct instances of `<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 (see
     make).

   * All existing subclasses of `<my-class>' are redefined, as though
     the `define-class' expressions that defined them were re-evaluated
     following the redefinition of `<my-class>', and the class
     redefinition process described here is applied recursively to the
     redefined subclasses.

   * Once all of its instances and subclasses have been updated, the
     class metaobject previously bound to the variable `<my-class>' is
     no longer needed and so can be allowed to be garbage collected.

To keep things tidy, GOOPS also needs to do a little housekeeping on
methods that are associated with the redefined class.

   * 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.

   * Any generic function method that uses the old `<my-class>'
     metaobject as one of its formal parameter specializers must be
     updated to refer to the new `<my-class>' metaobject.  (Whenever a
     new generic function method is defined, `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.)

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...

Customizing Class Redefinition
------------------------------

When `define-class' notices that a class is being redefined, it
constructs the new class metaobject as usual, and then invokes the
`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 `<class>', class redefinition behaviour can be
customized by defining a `class-redefinition' method that is
specialized for the relevant metaclasses.

 - generic: class-redefinition
     Handle the class redefinition from OLD-CLASS to NEW-CLASS, and
     return the new class metaobject that should be bound to the
     variable specified by `define-class''s first argument.

 - method: class-redefinition (old-class <class>) (new-class <class>)
     Implements GOOPS' default class redefinition behaviour, as
     described in Default Class Redefinition Behaviour.
     Returns the metaobject for the new class definition.

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.

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 `class-redefinition'
method that is specialized for this metaclass:

     (define-class <can-be-nameless> (<class>))

     (define-method (class-redefinition (old <can-be-nameless>) (new <class>))
       new)

When customization can be as easy as this, aren't you glad that GOOPS
implements the far more difficult strategy as its default!

Finally, note that, if `class-redefinition' itself is not customized,
the default `class-redefinition' method invokes three further generic
functions that could be individually customized:

   * (remove-class-accessors! OLD-CLASS)

   * (update-direct-method! METHOD OLD-CLASS NEW-CLASS)

   * (update-direct-subclass! SUBCLASS OLD-CLASS NEW-CLASS)

and the default methods for these generic functions invoke further
generic functions, and so on...  The detailed protocol for all of these
is described in MOP Specification.

Changing the Class of an Instance
=================================

You can change the class of an existing instance by invoking the
generic function `change-class' with two arguments: the instance and
the new class.

 - generic: change-class

The default method for `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 (see
slot-init-function).

 - method: change-class (obj <object>) (new <class>)
     Modify instance OBJ to make it an instance of class NEW.

     The value of each of OBJ's slots is preserved only if a similarly
     named slot exists in NEW; any other slot values are discarded.

     The slots in NEW that do not correspond to any of OBJ's
     pre-existing slots are initialized according to NEW's slot
     definitions' init functions.

Customized change of class behaviour can be implemented by defining
`change-class' methods that are specialized either by the class of the
instances to be modified or by the metaclass of the new class.

When a class is redefined (see Redefining a Class), and the default
class redefinition behaviour is not overridden, GOOPS (eventually)
invokes the `change-class' generic function for each existing instance
of the redefined class.

Introspection
=============

"Introspection", also known as "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++.

Nothing in C++ allows a running program to obtain answers to the
following types of question:

   * What are the data members of this object or class?

   * What classes does this class inherit from?

   * Is this method call virtual or non-virtual?

   * If I invoke `Employee::adjustHoliday()', what class contains the
     `adjustHoliday()' method that will be applied?

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.

Classes
-------

 - primitive procedure: class-name class
     Return the name of class CLASS.  This is the value of the CLASS
     metaobject's `name' slot.

 - primitive procedure: class-direct-supers class
     Return a list containing the direct superclasses of CLASS.  This
     is the value of the CLASS metaobject's `direct-supers' slot.

 - primitive procedure: class-direct-slots class
     Return a list containing the slot definitions of the direct slots
     of CLASS.  This is the value of the CLASS metaobject's
     `direct-slots' slot.

 - primitive procedure: class-direct-subclasses class
     Return a list containing the direct subclasses of CLASS.  This is
     the value of the CLASS metaobject's `direct-subclasses' slot.

 - primitive procedure: class-direct-methods class
     Return a list of all the generic function methods that use CLASS
     as a formal parameter specializer.  This is the value of the CLASS
     metaobject's `direct-methods' slot.

 - primitive procedure: class-precedence-list class
     Return the class precedence list for class CLASS (see Class precedence list).
     This is the value of the CLASS metaobject's
     `cpl' slot.

 - primitive procedure: class-slots class
     Return a list containing the slot definitions for all CLASS's
     slots, including any slots that are inherited from superclasses.
     This is the value of the CLASS metaobject's `slots' slot.

 - primitive procedure: class-environment class
     Return the value of CLASS's `environment' slot.  [ *fixme*  I
     don't know what this value is used for. ]

 - procedure: class-subclasses class
     Return a list of all subclasses of CLASS.

 - procedure: class-methods class
     Return a list of all methods that use CLASS or a subclass of CLASS
     as one of its formal parameter specializers.

Slots
-----

 - procedure: class-slot-definition class slot-name
     Return the slot definition for the slot named SLOT-NAME in class
     CLASS.  SLOT-NAME should be a symbol.

 - procedure: slot-definition-name slot-def
     Extract and return the slot name from SLOT-DEF.

 - procedure: slot-definition-options slot-def
     Extract and return the slot options from SLOT-DEF.

 - procedure: slot-definition-allocation slot-def
     Extract and return the slot allocation option from SLOT-DEF.  This
     is the value of the `#:allocation' keyword (see allocation),
     or `#:instance' if the `#:allocation' keyword is absent.

 - procedure: slot-definition-getter slot-def
     Extract and return the slot getter option from SLOT-DEF.  This is
     the value of the `#:getter' keyword (see getter),
     or `#f' if the `#:getter' keyword is absent.

 - procedure: slot-definition-setter slot-def
     Extract and return the slot setter option from SLOT-DEF.  This is
     the value of the `#:setter' keyword (see setter),
     or `#f' if the `#:setter' keyword is absent.

 - procedure: slot-definition-accessor slot-def
     Extract and return the slot accessor option from SLOT-DEF.  This
     is the value of the `#:accessor' keyword (see accessor),
     or `#f' if the `#:accessor' keyword is absent.

 - procedure: slot-definition-init-value slot-def
     Extract and return the slot init-value option from SLOT-DEF.  This
     is the value of the `#:init-value' keyword (see init-value),
     or the unbound value if the `#:init-value' keyword is
     absent.

 - procedure: slot-definition-init-form slot-def
     Extract and return the slot init-form option from SLOT-DEF.  This
     is the value of the `#:init-form' keyword (see init-form),
     or the unbound value if the `#:init-form' keyword is
     absent.

 - procedure: slot-definition-init-thunk slot-def
     Extract and return the slot init-thunk option from SLOT-DEF.  This
     is the value of the `#:init-thunk' keyword (see init-thunk),
     or `#f' if the `#:init-thunk' keyword is absent.

 - procedure: slot-definition-init-keyword slot-def
     Extract and return the slot init-keyword option from SLOT-DEF.
     This is the value of the `#:init-keyword' keyword (see
     init-keyword), or `#f' if the `#:init-keyword'
     keyword is absent.

 - procedure: slot-init-function class slot-name
     Return the initialization function for the slot named SLOT-NAME in
     class CLASS.  SLOT-NAME should be a symbol.

     The returned initialization function incorporates the effects of
     the standard `#:init-thunk', `#:init-form' and `#:init-value' slot
     options.  These initializations can be overridden by the
     `#:init-keyword' slot option or by a specialized `initialize'
     method, so, in general, the function returned by
     `slot-init-function' may be irrelevant.  For a fuller discussion,
     see init-value.

Instances
---------

 - primitive procedure: class-of value
     Return the GOOPS class of any Scheme VALUE.

 - primitive procedure: instance? object
     Return `#t' if OBJECT is any GOOPS instance, otherwise `#f'.

 - procedure: is-a? object class
     Return `#t' if OBJECT is an instance of CLASS or one of its
     subclasses.

Implementation notes: `is-a?' uses `class-of' and
`class-precedence-list' to obtain the class precedence list for OBJECT.

Generic Functions
-----------------

 - primitive procedure: generic-function-name gf
     Return the name of generic function GF.

 - primitive procedure: generic-function-methods gf
     Return a list of the methods of generic function GF.  This is the
     value of the GF metaobject's `methods' slot.

Generic Function Methods
------------------------

 - primitive procedure: method-generic-function method
     Return the generic function that METHOD belongs to.  This is the
     value of the METHOD metaobject's `generic-function' slot.

 - primitive procedure: method-specializers method
     Return a list of METHOD's formal parameter specializers .  This is
     the value of the METHOD metaobject's `specializers' slot.

 - primitive procedure: method-procedure method
     Return the procedure that implements METHOD.  This is the value of
     the METHOD metaobject's `procedure' slot.

 - generic: method-source
 - method: method-source (m <method>)
     Return an expression that prints to show the definition of method
     M.

          (define-generic cube)

          (define-method (cube (n <number>))
            (* n n n))

          (map method-source (generic-function-methods cube))
          =>
          ((method ((n <number>)) (* n n n)))

Miscellaneous Functions
=======================

Administration Functions
------------------------

This section describes administrative, non-technical GOOPS functions.

 - primitive: goops-version
     Return the current GOOPS version as a string, for example "0.2".

Error Handling
--------------

The procedure `goops-error' is called to raise an appropriate error by
the default methods of the following generic functions:

   * `slot-missing' (see slot-missing)

   * `slot-unbound' (see slot-unbound)

   * `no-method' (see no-method)

   * `no-applicable-method' (see no-applicable-method)

   * `no-next-method' (see no-next-method)

If you customize these functions for particular classes or metaclasses,
you may still want to use `goops-error' to signal any error conditions
that you detect.

 - procedure: goops-error format-string . args
     Raise an error with key `goops-error' and error message constructed
     from FORMAT-STRING and ARGS.  Error message formatting is as done
     by `scm-error'.

Object Comparisons
------------------

 - generic: eqv?
 - method: eqv? ((x <top>) (y <top>))
 - generic: equal?
 - method: equal? ((x <top>) (y <top>))
 - generic: =
 - method: = ((x <number>) (y <number>))
     Generic functions and default (unspecialized) methods for
     comparing two GOOPS objects.

     The default method for `eqv?' returns `#t' for all values that are
     equal in the sense defined by R5RS and the Guile reference manual,
     otherwise `#f'.  The default method for `equal?' returns `#t' or
     `#f' in the sense defined by R5RS and the Guile reference manual.
     If no such comparison is defined, `equal?' returns the result of a
     call to `eqv?'.  The default method for = returns `#t' if X and Y
     are numerically equal, otherwise `#f'.

     Application class authors may wish to define specialized methods
     for `eqv?', `equal?' and `=' 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.

Cloning Objects
---------------

 - generic: shallow-clone
 - method: shallow-clone (self <object>)
     Return a "shallow" clone of 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.

 - generic: deep-clone
 - method: deep-clone (self <object>)
     Return a "deep" clone of 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 `instance?'), it is cloned by calling
     `deep-clone' on that value.  Other slot values are copied either
     as immediate values or by reference.

Write and Display
-----------------

 - primitive generic: write object port
 - primitive generic: display object port
     When GOOPS is loaded, `write' and `display' become generic
     functions with special methods for printing

        * objects - instances of the class `<object>'

        * foreign objects - instances of the class `<foreign-object>'

        * classes - instances of the class `<class>'

        * generic functions - instances of the class `<generic>'

        * methods - instances of the class `<method>'.

     `write' and `display' print non-GOOPS values in the same way as
     the Guile primitive `write' and `display' functions.

MOP Specification
*****************

For an introduction to metaobjects and the metaobject protocol, see
Metaobjects and the Metaobject Protocol.

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.

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,

   * the `(initialize INSTANCE INITARGS)' invocation in the default
     `make-instance' method is customizable, because the type of the
     `INSTANCE' argument is determined by the class that was passed to
     `make-instance'.

   * the `(make <generic> #:name ',name)' invocation in `define-generic'
     is not customizable, because all of its arguments have lexically
     determined types.

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.

For each customizable generic function invocation, the "invocation
protocol" is explained by specifying

   * what, conceptually, the applied method is intended to do

   * what assumptions, if any, the caller makes about the applied
     method's side effects

   * what the caller expects to get as the applied method's return
     value.

Class Definition
================

`define-class' (syntax)

   * `class' (syntax)

        * `make-class' (procedure)

             * `make METACLASS ...' (generic)

               METACLASS is the metaclass of the class being defined,
               either taken from the `#:metaclass' class option or
               computed by `ensure-metaclass'.  The applied method must
               create and return the fully initialized class metaobject
               for the new class definition.

   * `class-redefinition OLD-CLASS NEW-CLASS' (generic)

     `define-class' calls `class-redefinition' if the variable
     specified by its first argument already held a GOOPS class
     definition.  OLD-CLASS and 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 `define-class''s variable.  The
     default class redefinition protocol is described in Class Redefinition.

The `(make METACLASS ...)' invocation above will create an class
metaobject with metaclass METACLASS.  By default, this metaobject will
be initialized by the `initialize' method that is specialized for
instances of type `<class>'.

`initialize <class> INITARGS' (method)

   * `compute-cpl CLASS' (generic)

     The applied method should compute and return the class precedence
     list for CLASS as a list of class metaobjects.  When `compute-cpl'
     is called, the following CLASS metaobject slots have all been
     initialized: `name', `direct-supers', `direct-slots',
     `direct-subclasses' (empty), `direct-methods'.  The value returned
     by `compute-cpl' will be stored in the `cpl' slot.

   * `compute-slots CLASS' (generic)

     The applied method should compute and return the slots (union of
     direct and inherited) for CLASS as a list of slot definitions.
     When `compute-slots' is called, all the CLASS metaobject slots
     mentioned for `compute-cpl' have been initialized, plus the
     following: `cpl', `redefined' (`#f'), `environment'.  The value
     returned by `compute-slots' will be stored in the `slots' slot.

   * `compute-get-n-set CLASS SLOT-DEF' (generic)

     `initialize' calls `compute-get-n-set' for each slot computed by
     `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:
     `(list GET SET)'.

     The closures returned by `compute-get-n-set' are stored as part of
     the value of the CLASS metaobject's `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

          `(SLOT-NAME-SYMBOL INIT-FUNCTION . INDEX)'

     or like

          `(SLOT-NAME-SYMBOL INIT-FUNCTION GET SET)'

     Where the get and set closures are replaced by INDEX, the slot is
     an instance slot and 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, GET and SET are the closures returned by
     `compute-get-n-set'.

     The structure of the `getters-n-setters' slot value is important
     when understanding the next customizable generic functions that
     `initialize' calls...

   * `compute-getter-method CLASS GNS' (generic)

     `initialize' calls `compute-getter-method' for each of the class's
     slots (as determined by `compute-slots') that includes a
     `#:getter' or `#:accessor' slot option.  GNS is the element of the
     CLASS metaobject's `getters-n-setters' slot that specifies how the
     slot in question is referenced and set, as described above under
     `compute-get-n-set'.  The applied method should create and return
     a method that is specialized for instances of type 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. ] `initialize' uses `add-method!' to add the returned
     method to the generic function named by the slot definition's
     `#:getter' or `#:accessor' option.

   * `compute-setter-method CLASS GNS' (generic)

     `compute-setter-method' is invoked with the same arguments as
     `compute-getter-method', for each of the class's slots that
     includes a `#:setter' or `#:accessor' slot option.  The applied
     method should create and return a method that is specialized for
     instances of type CLASS and uses the set closure to set the slot's
     value.  `initialize' then uses `add-method!' to add the returned
     method to the generic function named by the slot definition's
     `#:setter' or `#:accessor' option.

Instance Creation
=================

`make <class> . INITARGS' (method)

   * `allocate-instance CLASS INITARGS' (generic)

     The applied `allocate-instance' method should allocate storage for
     a new instance of class CLASS and return the uninitialized
     instance.

   * `initialize INSTANCE INITARGS' (generic)

     INSTANCE is the uninitialized instance returned by
     `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.

Class Redefinition
==================

The default `class-redefinition' method, specialized for classes with
the default metaclass `<class>', has the following internal protocol.

`class-redefinition (OLD <CLASS>) (NEW <CLASS>)' (method)

   * `remove-class-accessors! OLD' (generic)

   * `update-direct-method! METHOD OLD NEW' (generic)

   * `update-direct-subclass! SUBCLASS OLD NEW' (generic)

The default `update-direct-subclass!' method invokes
`class-redefinition' recursively to handle the redefinition of
subclasses.

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 `change-class'.

The default `change-class' method copies slot values from the old to
the modified instance, and initializes new slots, as described in
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.

`change-class (OLD-INSTANCE <OBJECT>) (NEW <CLASS>)' (method)

   * `update-instance-for-different-class OLD-INSTANCE NEW-INSTANCE'
     (generic)

     `change-class' invokes `update-instance-for-different-class' as
     the last thing that it does before returning.  The applied method
     can make any further adjustments to NEW-INSTANCE that are required
     to complete or modify the change of class.  The return value from
     the applied method is ignored.

     The default `update-instance-for-different-class' method does
     nothing.

Method Definition
=================

`define-method' (syntax)

   * `add-method! TARGET METHOD' (generic)

     `define-method' invokes the `add-method!' generic function to
     handle adding the new method to a variety of possible targets.
     GOOPS includes methods to handle TARGET as

        * a generic function (the most common case)

        * a procedure

        * a primitive generic (see Extending Guiles Primitives)

     By defining further methods for `add-method!', you can
     theoretically handle adding methods to further types of target.

Generic Function Invocation
===========================

[ *fixme* Description required here. ]

`apply-generic'

   * `no-method'

   * `compute-applicable-methods'

   * `sort-applicable-methods'

   * `apply-methods'

   * `no-applicable-method'

`sort-applicable-methods'

   * `method-more-specific?'

`apply-methods'

   * `apply-method'

`next-method'

   * `no-next-method'