Generic dispatch system
=======================

Scheme48 supports a CLOS-style generic procedure dispatch system, based on type predicates.  The main interface is exported by methods. The internals of the system are exposed by the meta-methods structure, but they are not documented here.  The generic dispatch system is used in Scheme48's Writer, writer and numeric system.

Types in Scheme48's generic dispatch system are represented using type predicates, rather than having every object have a single, well-defined `class.'  The naming convention for simple types is to prefix the type name with a colon.  The types support multiple inheritance.  Method specificity is determined based on descending order of argument importance.  That is, given two methods, M & N, such that they are both applicable to a given sequence of arguments, and an index I into that sequence, such that I is the first index in M's & N's lists of argument type specifiers, from left to right, where the type differs: if the type for M's argument at I is more specific than the corresponding type in N's specifiers, M is considered to be more specific than N, even if the remaining argument type specifiers in N are more specific.

 -- syntax: define-simple-type name (supertype ...) predicate
     Defines NAME to be a simple type with the given predicate and the given supertypes.

 -- procedure: singleton value returns simple-type
     Creates a singleton type that matches only VALUE.

 -- syntax: define-generic proc-name method-table-name [prototype]
     Defines PROC-NAME to be a generic procedure that, when invoked, will dispatch on its arguments via the method table that METHOD-TABLE-NAME is defined to be and apply the most specific method it can determine defined in the METHOD-TABLE-NAME method table to its arguments.  The convention for naming variables that will be bound to method tables is to add an ampersand to the front of the name.  PROTOTYPE is a suggestion for what method prototypes should follow the shape of, but it is currently ignored.

 -- syntax: define-method method-table prototype body
     Adds a method to METHOD-TABLE, which is usually one defined by define-generic. (There is an internal interface, a sort of meta-object protocol, to the method dispatch system, but it is not yet documented.)  PROTOTYPE should be a list whose elements may be either identifiers, in which case that parameter is not used for dispatching, or lists of two elements, the car of which is the parameter name and the cadr of which should evaluate to the type on which to dispatch.  As in many generic dispatch systems of similar designs, methods may invoke the next-most-specific method.  By default, the name next-method is bound in BODY to a nullary procedure that calls the next-most-specific method.  The name of this procedure may be specified by the user by putting the sequence "next" NEXT-METHOD-NAME in PROTOTYPE, in which case it will be NEXT-METHOD-NAME that is bound to that procedure.  For example:

          (define-method &frob ((foo :bar) "next" frobozz)
            (if (mumble? foo)
                (frobozz)     ; Invoke the next method.
                (yargh blargle foo))) lisp

A number of simple types are already defined & exported by the methods structure.  Entries are listed as TYPE-NAME <- (SUPERTYPE ...), PREDICATE

  * :values <- (), (lambda (x) #t) --- Abstract supertype of all run-time values

  * :value <- (:values), (lambda (x) #t) --- Abstract supertype of all first-class values

  * :zero <- (:values), (lambda (x) #f) --- Type that no objects satisfy

  * :number <- (:value), number?

  * :complex <- (:number), complex? --- (This happens to be equivalent to :number.)

  * :real <- (:complex), real?

  * :rational <- (:real), rational?

  * :integer <- (:rational), integer?

  * :exact-integer <- (:integer), (lambda (x) (and (integer? x) (exact? x)))

  * :boolean <- (:value), boolean?

  * :symbol <- (:value), symbol?

  * :char <- (:value), char?

  * :null <- (:value), null?

  * :pair <- (:value), pair?

  * :vector <- (:value), vector?

  * :string <- (:value), string?

  * :procedure <- (:value), procedure?

  * :input-port <- (:value), input-port?

  * :output-port <- (:value), output-port?

  * :eof-object <- (:value), eof-object?

  * :record <- (:value), record?