# Documentation for '`swindle/tiny-clos.ss`'

This module is the core object system. It is a heavily hacked version of the original Tiny-CLOS code from Xerox, but it has been fitted to MzScheme, optimized and extended. See the source file for a lot of details about how the CLOS magic is created.

[There is one difference between Swindle and Tiny-CLOS: the meta object hierarchy is assumed to be using only single inheritance, or if there is multiple inheritance then the built in meta objects should come first to make the slots allocated in the same place. This should not be a problem in realistic situations.]

`???` | [value]

      This is MzScheme's 'unspecified' value which is used as the default
      value for unbound slots.  It is provided so you can check if a slot is
      unbound.

### Low level functionality

    (These functions should be used with caution, since they make shooting
    legs in exotic ways extremely easy.)

`(change-class! object new-class initargs ...)` | [procedure]

      This operation changes the class of the given 'object' to the given
      'new-class'.  The way this is done is by creating a fresh instance of
      'new-class', then copying all slot values from 'object' to the new
      instance for all shared slot names.  Finally, the new instance's set
      of slots is used for the original object with the new class, so it
      preserves its identity.

`(set-instance-proc! object proc)` | [syntax]

      This function sets the procedure of an entity object.  It is useful
      only for making new entity classes.

### Basic functionality

`(instance? x)` | [procedure]
`(object? x)` | [procedure]

      These two are synonyms: a predicate that returns #t for objects that
      are allocated and managed by Swindle.

`(class-of x)` | [procedure]

      Return the class object of 'x'.  This will either be a Swindle class
      for objects, or a built-in class for other Scheme values.

`(slot-ref obj slot)` | [procedure]

      Pull out the contents of the slot named 'slot' in the given 'obj'.
      Note that slot names are usually symbols, but can be other values as
      well.

`(slot-set! obj slot new)` | [procedure]

      Change the contents of the 'slot' slot of 'obj' to the given 'new'
      value.

`(set-slot-ref! obj slot new)` | [procedure]

      An alias for 'slot-set!', to enable using 'setf!' on it.

`(slot-bound? object slot)` | [procedure]

      Checks if the given 'slot' is bound in 'object'.  See also '???'
      above.

## Singleton and Struct Specifiers

`(singleton x)` | [procedure]

      Returns a singleton specification.  Singletons can be used as type
      specifications that have only one element in them so you can
      specialize methods on unique objects.

      This is actually just a list with the symbol 'singleton' in its head
      and the value, but this function uses a hash table to always return
      the same object for the same value.  For example:
        => (singleton 1)
        (singleton 1)
        => (eq? (singleton 1) (singleton 1))
        #t
      but if the input objects are not 'eq?', the result isn't either:
        => (eq? (singleton "1") (singleton "1"))
        #f
      Only 'eq?' is used to compare objects.

`(singleton? x)` | [procedure]

      Determines if something is a singleton specification (which is any
      list with a head containing the symbol 'singleton').

`(singleton-value x)` | [procedure]

      Pulls out the value of a singleton specification.

    Also note that MzScheme struct types are converted to appropriate
    Swindle classes.  This way, it is possible to have Swindle generic
    functions that work with struct type specializers.

`(struct-type->class struct-type)` | [procedure]

      This function is used to convert a struct-type to a corresponding
      Swindle subclass of '<struct>'.  See the MzScheme manual for details
      on struct types.

### Common accessors

`(class-direct-slots class)` | [procedure]
`(class-direct-supers class)` | [procedure]
`(class-slots class)` | [procedure]
`(class-cpl class)` | [procedure]
`(class-name class)` | [procedure]
`(class-initializers class)` | [procedure]

      Accessors for class objects (look better than using 'slot-ref').

`(generic-methods generic)` | [procedure]
`(generic-arity generic)` | [procedure]
`(generic-name generic)` | [procedure]
`(generic-combination generic)` | [procedure]

      Accessors for generic function objects.

`(method-specializers method)` | [procedure]
`(method-procedure method)` | [procedure]
`(method-qualifier method)` | [procedure]
`(method-name method)` | [procedure]
`(method-arity method)` | [procedure]

      Accessors for method objects.  'method-arity' is not really an
      accessor, it is deduced from the arity of the procedure (minus one for
      the 'call-next-method' argument).

### Basic classes

``<class>`` | [class]

      This is the "mother of all classes": every Swindle class is an
      instance of '<class>'.
      Slots:
      * direct-supers:  direct superclasses
      * direct-slots:   direct slots, each a list of a name and options
      * cpl:            class precedence list (classes list this to <top>)
      * slots:          all slots (like direct slots)
      * nfields:        number of fields
      * field-initializers: a list of functions to initialize slots
      * getters-n-setters:  an alist of slot-names, getters, and setters
      * name:           class name (usually the defined identifier)
      * initializers:   procedure list that perform additional initializing
      See the 'clos' documentation for available class and slot keyword
      arguments and their effect.

      Instance of '<class>', subclass of '<object>'.

``<top>`` | [class]

      This is the "mother of all values": every value is an instance of
      '<top>' (including standard Scheme values).

      Instance of '<class>'.

``<object>`` | [class]

      This is the "mother of all objects": every Swindle object is an
      instance of '<object>'.

      Instance of '<class>', subclass of '<top>'.

``<procedure-class>`` | [class]

      The class of all procedures classes, both standard Scheme procedures
      classes and entity (Swindle procedure objects) classes.  (Note that
      this is a class of *classes*).

      Instance of '<class>', subclass of '<class>'.

``<entity-class>`` | [class]

      The class of entity classes -- generic functions and methods.  An
      entity is a procedural Swindle object, something that you can apply as
      a function but it is still a Swindle object.  Note that this is the
      class of entity *classes* not of entities themselves.

      Instance of '<class>', subclass of '<procedure-class>'.

``<function>`` | [class]

      The class of all applicable values: methods, generic functions, and
      standard closures.

      Instance of '<class>', subclass of '<top>'.

``<generic>`` | [class]

      The class of generic functions: objects that contain method objects
      and calls the appropriate ones when applied.
      Slots:
      * methods:     a list of <method> objects
      * arity:       the generic arity (same for all of its methods)
      * name:        generic name
      * combination: a method combination function or #f, see
                     'make-generic-combination' below for details

      Instance of '<entity-class>', subclass of '<object>', '<function>'.

``<method>`` | [class]

      The class of methods: objects that are similar to Scheme closures,
      except that they have type specifiers attached.  Note that in contrast
      to Tiny CLOS, methods are applicable objects in Swindle -- they check
      supplied argument types when applied.
      Slots:
      * specializers: a list of class (and singleton) specializers
      * procedure:    the function (never call directly!)
      * qualifier:    some qualifier tag, used when applying a generic
      * name:         method name

      Instance of '<entity-class>', subclass of '<object>', '<function>'.

### Convenience functions

    These are some convenience functions -- no new syntax, just function
    wrappers for 'make' with some class and some slot values.  See 'clos'
    for a more sophisticated (and convenient) approach.

`(make-class direct-supers direct slots)` | [procedure]

      Creates a class object -- an instance of <class>.

`(make-generic-function [name/arity])` | [procedure]

      Creates a generic function object -- an instance of <generic>.  The
      argument can specify name and/or arguments number.

`(make-method specializers procedure)` | [procedure]

      Creates a method object -- an instance of <method>, using the given
      specializer list and procedure.  The procedure should have a first
      argument which is being used to access a 'call-next-method' call.

`(no-next-method generic method [args ...])` | [generic]
`(no-applicable-method generic [args ...])` | [generic]

      These two generic functions are equivalents to the ones in CL.  The
      first one is applied on a generic and a method in case there was no
      next method and 'call-next-method' was used.  The second is used when
      a generic was called but no matching primary methods were found.  The
      only difference is that in Swindle methods can be applied directly,
      and if 'call-next-method' is used, then 'no-next-method' gets '#f' for
      the generic argument.

## Generics in the instance initialization protocol

    The following generic functions are used as part of the protocol of
    instantiating an instance, and some are used specifically to instantiate
    class objects.

`(allocate-instance class initargs)` | [generic]

      This generic function is called to allocate an instance of a class.
      It is applied on the class object, and is expected to return the new
      instance object of that class.

`(initialize instance initargs)` | [generic]

      This generic is called to initialize an instance.  It is applied on
      the newly allocated object and the given initargs, and is not expected
      to return any meaningful value -- only do some side effects on the
      instance to initialize it.  When overriding this for a some class, it
      is not a good idea to skip 'call-next-method' since it is responsible
      for initializing slot values.

`(compute-getter-and-setter class slot allocator)` | [generic]

      This generic is used to get a getter and setter functions for a given
      slot.  It is passed the class object, the slot information (a list of
      a slot name and options), and an allocator function.  The allocator is
      a function that gets an initializer function and returns an index
      position for the new slot.  The return value should be a list of two
      elements -- a getter and a setter functions.

`(compute-cpl class)` | [generic]

      This generic is used to get the class-precedence-list for a class
      object.  The standard <class> object uses the 'compute-std-cpl' (see
      in the code) which flattens the class ancestors using a topological
      sort that resolve ambiguities left-to-right.

`(compute-slots class)` | [generic]

      This generic is used to compute all slot information for a given
      class, after its precedence list has been computed.  The standard
      <class> collects information from all preceding classes.

`(compute-apply-method method)` | [generic]

      This generic is used to compute the procedure that will get executed
      when a method is applied directly.

## Generics in the generic invocation protocol

    These generics are used for invocation of generic functions.  See the
    code to see how this circularity is achieved.

`((compute-apply-generic generic) args ...)` | [generic]

      This generic is used to compute the object (a closure) that is
      actually applied to execute the generic call.  The standard version
      uses 'compute-method' and 'compute-apply-methods' below, and caches
      the result.

`(compute-methods generic args)` | [generic]

      Computes the methods that should be applied for this generic
      invocation with args.  The standard code filters applicable methods
      and sorts them according to their specificness.  The return value is
      expected to depend only on the types of the arguments (and values if
      there are singleton specializers).

`((compute-method-more-specific? generic) mthd1 mthd2 args)` | [generic]

      Get a generic and return a function that gets two methods and a list
      of arguments and decide which of the two methods is more specific.
      This decision should only be based on the argument types, or values
      only in case of singletons.

`((compute-apply-methods generic methods) args ...)` | [generic]

      Gets a generic and returns a function that gets the given arguments
      for this call.  This function which it returns is the combination of
      all given methods.  The standard one arranges them by default using
      the 'call-next-method' argument that methods have.  Swindle extends
      this with qualified methods and applies 'before', 'after', and
      'around' methods in a similar way to CLOS: first the 'around' methods
      are applied (and they usually call their 'call-next-method' to
      continue but can return a different value), then all the 'before'
      methods are applied (with no 'call-next-method'), then all 'primary'
      methods as usual (remembering the return value), and finally the
      'after' methods (similar to the 'before', but in reverse specificness
      order).  If the generic has a 'combination' slot value, then it is a
      procedure that is used to combine the primary methods, but the
      auxiliary ones are still applied in the same way.  This is unlike CLOS
      where the standard combinations run only 'around' methods, and there
      is generally more control with method combinations, but in Swindle
      'compute-apply-methods' should be overridden for this.  See
      'make-generic-combination' for details about method combinations.

`(add-method generic method)` | [generic]

      This generic function is called to add a method to a generic function
      object.  This is an other change from the original Tiny CLOS where it
      was a normal function.

`(((make-generic-combination keys...) generic) tail args)` | [procedure]

      This function can be used to construct simple method combinations that
      can be used with the 'combination' slot of generic functions.  The
      combination itself is a function that gets a generic and returns a
      function that gets a list of method/procedure pairs (for optimization
      the method-procedures are pre taken) and the arguments and performs
      the call -- but this is only interesting if there's any need to
      implement a method combination directly, otherwise, the
      'make-generic-combination' interface should allow enough freedom.
      Note that when a method combination is used, 'around', 'before', and
      'after' are called around the primary call as usual, but the primaries
      are never called with a valid 'call-next-method' argument.

      The keyword arguments that can be taken determine the behavior of this
      combination.  Overall, it is roughly like a customizable version of a
      fold operation on the method calls.
      * :init
        - The initial value for this computation.  Defaults to null.
      * :combine
        - A function to be called on a method call result and the old value,
          and produces a new value.  The default is 'cons', which with an
          initial null value will collect the results into a reversed list.
      * :process-methods
        - A function that can be called on the initial list of
          method/procedure pairs to change it -- for example, it can be
          reversed to apply the methods from the least specific to the most
          specific.  No default.
      * :process-result
        - A function that can be called on the final resulting value to
          produce the actual return value.  For example, it can reverse back
          a list of accumulated values.  No default.
      * :control
        - If this parameter is specified, then the ':combine' argument is
          ignored.  The value given to ':control' should be a function of
          four arguments:
          1. a 'loop' function that should be called on some new value and
             some new tail;
          2. a 'val' argument that gets the current accumulated value;
          3. a 'this' thunk that can be called to apply the current method
             and return its result;
          4. a 'tail' value that holds the rest of the method/procedure list
             which can be sent to 'loop'.
          It should be clear now, that a ':control' argument can have a lot
          of control on the computation, it can abort, change arbitrary
          values and skip calling methods.  Note that if it won't call
          'loop' with an empty list, then a ':process-result' function will
          not be used as well.  See the pre-defined combinations in the
          source code to see examples of using this function.

`generic-+-combination` | [procedure]
`generic-list-combination` | [procedure]
`generic-min-combination` | [procedure]
`generic-max-combination` | [procedure]
`generic-append-combination` | [procedure]
`generic-append!-combination` | [procedure]
`generic-begin-combination` | [procedure]
`generic-and-combination` | [procedure]
`generic-or-combination` | [procedure]

      These are all functions that can be used as a 'combination' value for
      a generic function.  They work in the same way as the standard method
      combinations of CL.  Most of them do the obvious thing based on some
      function to combine the result.  The 'begin' combination simply
      executes all methods one by one and returns the last value, the 'and'
      and 'or' combinations will call them one by one until a false or true
      result is returned.  The source of these can be used as templates for
      defining more combinations.

### More class functionality

    (In the following, a 'class' can be a class, a singleton specifier, or a
    struct type.)

`(subclass? class1 class2)` | [procedure]

      Is 'class1' a subclass of 'class2'?

`(instance-of? x class)` | [procedure]

      Checks if 'x' is an instance of 'class' (or one of its subclasses).

`(class? x)` | [procedure]

      Determines whether 'x' is a class.

`(specializer? x)` | [procedure]

      Determines whether 'x' is a class, a singleton, or a struct-type.

`(more-specific? class1 class2 x)` | [procedure]

      Is 'class1' more specific than 'class2' for the given value?

## Swindle Customization Parameters

`*default-method-class*` | [parameter]
`*default-generic-class*` | [parameter]
`*default-class-class*` | [parameter]
`*default-entityclass-class*` | [parameter]

      These parameters specify default classes for the many constructor
      macros in 'clos'.

`*default-object-class*` | [parameter]

      This parameter contains a value which is automatically made a
      superclass for all classes.  Defaults to '<object>'.

`*make-safely*` | [parameter]

      Setting this parameter to #t will make Swindle perform sanity checks
      on given initargs for creating an object.  This will make things
      easier for debugging, but also slower.  Defaults to '#f'.  Note that
      the sanity checks are done in 'initialize'.

## Creating Instances

`(make class initargs ...)` | [generic]

      Create an instance of 'class', which can be any Swindle class (except
      for some special top-level classes and built-in classes).

      See the `Object Initialization Protocol' below for a description of
      generic functions that are involved in creating a Swindle object.

`(rec-make (name class arg ...) ...)` | [syntax]

      This is similar to:

        (letrec ([name (make class arg ...)] ...)
          (values name ...))

      except that the names are first bound to allocated instances with no
      initargs, and then they are initialized with all these bindings.  This
      is useful for situations where creating some instances needs other
      instances as values.  One sample usage is the way 'defclass' makes the
      class binding available for slot specifications like ':type'.  Note
      that this is a special form, which invokes 'allocate-instance' and
      'initialize' directly, so specializing 'make' on some input will not
      change the way 'rec-make' works.

## Built-in Classes

``<primitive-class>`` | [class]

      The class of all built-on classes.

      Instance of '<class>', subclass of '<class>'.

``<builtin>`` | [class]

      The superclass of all built-in classes.

      Instance of '<class>', subclass of '<top>'.

``<sequence>`` | [class]

      Instance of '<primitive-class>', subclass of '<builtin>'.

``<mutable>`` | [class]
``<immutable>`` | [class]
``<improper-list>`` | [class]
``<pair>`` | [class]
``<mutable-pair>`` | [class]
``<immutable-pair>`` | [class]
``<list>`` | [class]
``<nonempty-list>`` | [class]
``<mutable-nonempty-list>`` | [class]
``<immutable-nonempty-list>`` | [class]
``<null>`` | [class]
``<vector>`` | [class]
``<char>`` | [class]
``<string-like>`` | [class]
``<mutable-string-like>`` | [class]
``<immutable-string-like>`` | [class]
``<string>`` | [class]
``<mutable-string>`` | [class]
``<immutable-string>`` | [class]
``<bytes>`` | [class]
``<mutable-bytes>`` | [class]
``<immutable-bytes>`` | [class]
``<path>`` | [class]
``<symbol>`` | [class]
``<keyword>`` | [class]
``<real-keyword>`` | [class]
``<boolean>`` | [class]
``<number>`` | [class]
``<exact>`` | [class]
``<inexact>`` | [class]
``<complex>`` | [class]
``<real>`` | [class]
``<rational>`` | [class]
``<integer>`` | [class]
``<exact-complex>`` | [class]
``<inexact-complex>`` | [class]
``<exact-real>`` | [class]
``<inexact-real>`` | [class]
``<exact-rational>`` | [class]
``<inexact-rational>`` | [class]
``<exact-integer>`` | [class]
``<inexact-integer>`` | [class]
``<end-of-file>`` | [class]
``<port>`` | [class]
``<input-port>`` | [class]
``<output-port>`` | [class]
``<stream-port>`` | [class]
``<input-stream-port>`` | [class]
``<output-stream-port>`` | [class]
``<void>`` | [class]
``<box>`` | [class]
``<weak-box>`` | [class]
``<regexp>`` | [class]
``<byte-regexp>`` | [class]
``<parameter>`` | [class]
``<promise>`` | [class]
``<exn>`` | [class]
``<exn:fail>`` | [class]
``<exn:break>`` | [class]
``<semaphore>`` | [class]
``<hash-table>`` | [class]
``<subprocess>`` | [class]
``<thread>`` | [class]
``<syntax>`` | [class]
``<identifier-syntax>`` | [class]
``<namespace>`` | [class]
``<custodian>`` | [class]
``<tcp-listener>`` | [class]
``<security-guard>`` | [class]
``<will-executor>`` | [class]
``<struct-type>`` | [class]
``<inspector>`` | [class]
``<pseudo-random-generator>`` | [class]
``<compiled-expression>`` | [class]
``<unknown-primitive>`` | [class]

      These classes represent built-in objects.  See the class hierarchy
      below for a complete description of the relations between these
      classes.

``<struct>`` | [class]

      Instance of '<primitive-class>', subclass of '<builtin>'.

``<opaque-struct>`` | [class]

      These are also classes for built-in objects, but they are classes for
      MzScheme structs -- which can be used like Swindle classes since they
      will get converted to appropriate Swindle subclasses of '<struct>'.
      '<opaque-struct>' is a class of structs that are hidden -- see the
      documentation for 'struct-info' and the 'skipped?' result.  Note that
      structs can be used as long as they can be inspected -- otherwise, we
      can't even know that they are structs with 'struct?' (this means that
      <opaque-struct> can only appear in the cpl of a struct class that
      inherits from a struct which is not under the current inspector).

``<procedure>`` | [class]

      The class of all Scheme procedures.

      Instance of '<procedure-class>', subclass of '<builtin>', '<function>'.

``<primitive-procedure>`` | [class]

      The class of all primitive MzScheme procedures.

      Instance of '<procedure-class>', subclass of '<procedure>'.

`(builtin? x)` | [procedure]
`(function? x)` | [procedure]
`(generic? x)` | [procedure]
`(method? x)` | [procedure]

      Predicates for instances of <builtin>, <function>, <generic>, and
      <method>.

## Class Hierarchy

    In the following, every class's class is specified after a colon.  Also,
    some classes appear in more than once place due to multiple-inheritance.

      <top> : <class>
        <object> : <class>
          <class> : <class>
            <procedure-class> : <class>
              <entity-class> : <class>
            <primitive-class> : <class>
          <generic> : <entity-class>
          <method> : <entity-class>
        <function> : <class>
          <generic> : <entity-class>
          <method> : <entity-class>
          <procedure> : <procedure-class>
            <primitive-procedure> : <procedure-class>
        <builtin> : <class>
          <sequence> : <primitive-class>
            <improper-list> : <primitive-class>
              <pair> : <primitive-class>
                <mutable-pair> : <primitive-class>
                <immutable-pair> : <primitive-class>
                <nonempty-list> : <primitive-class>
                  <mutable-nonempty-list> : <primitive-class>
                  <immutable-nonempty-list> : <primitive-class>
              <list> : <primitive-class>
                <nonempty-list> : <primitive-class>
                  <mutable-nonempty-list> : <primitive-class>
                  <immutable-nonempty-list> : <primitive-class>
                <null> : <primitive-class>
            <vector> : <primitive-class>
            <string-like> : <primitive-class>
              <string> : <primitive-class>
                <mutable-string> : <primitive-class>
                <immutable-string> : <primitive-class>
              <bytes> : <primitive-class>
                <mutable-bytes> : <primitive-class>
                <immutable-bytes> : <primitive-class>
              <path> : <primitive-class>
          <mutable> : <primitive-class>
            <mutable-pair> : <primitive-class>
            <mutable-nonempty-list> : <primitive-class>
            <mutable-string-like> : <primitive-class>
              <mutable-string> : <primitive-class>
              <mutable-bytes> : <primitive-class>
            <vector>
            <box>
          <immutable> : <primitive-class>
            <immutable-nonempty-list> : <primitive-class>
            <immutable-pair> : <primitive-class>
            <immutable-string-like> : <primitive-class>
              <immutable-string> : <primitive-class>
              <immutable-bytes> : <primitive-class>
              <path> : <primitive-class>
          <char> : <primitive-class>
          <symbol> : <primitive-class>
            <keyword> : <primitive-class>
          <real-keyword> : <primitive-class>
          <boolean> : <primitive-class>
          <number> : <primitive-class>
            <complex> : <primitive-class>
              <exact-complex> : <primitive-class>
              <inexact-complex> : <primitive-class>
              <real> : <primitive-class>
                <exact-real> : <primitive-class>
                <inexact-real> : <primitive-class>
                <rational> : <primitive-class>
                  <integer> : <primitive-class>
                  <exact-rational> : <primitive-class>
                  <inexact-rational> : <primitive-class>
                    <exact-integer> : <primitive-class>
                    <inexact-integer> : <primitive-class>
            <exact> : <primitive-class>
              <exact-complex> : <primitive-class>
                <exact-real> : <primitive-class>
                  <exact-rational> : <primitive-class>
                    <exact-integer> : <primitive-class>
            <inexact> : <primitive-class>
              <inexact-complex> : <primitive-class>
                <inexact-real> : <primitive-class>
                  <inexact-rational> : <primitive-class>
                    <inexact-integer> : <primitive-class>
          <end-of-file> : <primitive-class>
          <port> : <primitive-class>
            <input-port> : <primitive-class>
              <input-stream-port> : <primitive-class>
            <output-port> : <primitive-class>
              <output-stream-port> : <primitive-class>
            <stream-port> : <primitive-class>
              <input-stream-port> : <primitive-class>
              <output-stream-port> : <primitive-class>
          <void> : <primitive-class>
          <box> : <primitive-class>
            <weak-box> : <primitive-class>
          <regexp> : <primitive-class>
          <byte-regexp> : <primitive-class>
          <parameter> : <primitive-class>
          <promise> : <primitive-class>
          <exn> : <primitive-class>
            <exn:fail> : <primitive-class>
            <exn:break> : <primitive-class>
          <semaphore> : <primitive-class>
          <hash-table> : <primitive-class>
          <subprocess> : <primitive-class>
          <thread> : <primitive-class>
          <syntax> : <primitive-class>
            <identifier-syntax> : <primitive-class>
          <namespace> : <primitive-class>
          <custodian> : <primitive-class>
          <tcp-listener> : <primitive-class>
          <security-guard> : <primitive-class>
          <will-executor> : <primitive-class>
          <inspector> : <primitive-class>
          <pseudo-random-generator> : <primitive-class>
          <compiled-expression> : <primitive-class>
          <unknown-primitive> : <primitive-class>
          <procedure> : <procedure-class>
            <primitive-procedure> : <procedure-class>
          <struct> : <primitive-class>
            <opaque-struct> : <primitive-class>
            ... struct type classes ...

## Object Initialization Protocol

    This is the initialization protocol.  All of these are generic
    functions (unlike the original Tiny CLOS).  See the individual
    descriptions above for more details.

      make
        allocate-instance
        initialize
      class initialization only:
        compute-cpl
        compute-slots
        compute-getter-and-setter
      method initialization only:
        compute-apply-method
      add-method
        compute-apply-generic
          compute-methods
            compute-method-more-specific?
          compute-apply-methods