1. Introduction
    1. Defining forms
    2. define-class
    3. define-generic
    4. define-method
    5. Base language
      1. add-method
      2. instance?
      3. make
      4. make-class
      5. make-generic
      6. make-method
      7. slot-ref
      8. slot-set!
      9. slot@
    6. Introspection
      1. class-cpl
      2. class-direct-slots
      3. class-direct-supers
      4. class-of
      5. class-name
      6. class-slots
      7. generic-methods
      8. method-specializers
      9. method-procedure
      10. subclass?
      11. instance-of?
    7. Intercessory protocol
      1. allocate-instance
      2. compute-apply-generic
      3. compute-apply-methods
      4. compute-methods
      5. compute-cpl
      6. compute-getter-and-setter
      7. compute-method-more-specific?
      8. compute-slots
      9. initialize
    8. Additional protocol
      1. describe-object
      2. print-object
    9. Utility procedures
      1. initialize-slots
      2. make/copy
    10. Builtin classes
      1. <primitive>
      2. boolean
      3. symbol
      4. char
      5. vector
      6. null
      7. pair
      8. number
      9. integer
      10. exact
      11. inexact
      12. string
      13. port
      14. environment
      15. end-of-file
      16. input-port
      17. output-port
      18. procedure
      19. byte-vector ; DEPRECATED
      20. blob
      21. structure
      22. hash-table
      23. queue
      24. class
      25. entity-class
      26. generic
      27. method
      28. object
      29. procedure-class
      30. condition
      31. continuation
      32. array
      33. char-set
      34. time
      35. u8vector
      36. s8vector
      37. u16vector
      38. s16vector
      39. u32vector
      40. s32vector
      41. f32vector
      42. f64vector
      43. lock
      44. mmap
      45. pointer
      46. tagged-pointer
      47. swig-pointer
      48. locative
      49. promise
      50. tcp-listener
      51. regexp
      52. c++-object
    11. Extending class-of
      1. define-primitive-class
      2. define-structure-class
      3. define-tagged-pointer-class
      4. define-extended-procedure-class
  2. Authors
  3. License
  4. Version History

Introduction

This extension is a port of Gregor Kiczales TinyCLOS with numerous modifications.

Note: Before CHICKEN version 2.424, TinyCLOS was a core unit of CHICKEN. With CHICKEN version 2.424 and onwards, TinyCLOS is not part of the core, it is an an egg extension.

Defining forms

define-class

[syntax] (define-class NAME (SUPERCLASS1 ...) (SLOTNAME1 ...) [METACLASS])

Sets the variable NAME to a new class (a new instance of the class <class>). SUPERCLASS1 ... is a list of superclasses of the newly created class. If no superclasses are given, then <object> is assumed. SLOTNAME1 ... are the names of the direct slots of the class. if METACLASS is provided, then the new class-instance is an instance of METACLASS instead of <class>.

(define-class NAME (SUPER) (SLOT1 SLOT2) META)

is equivalent to

(define NAME
  (make META 
    'name 'NAME
    'direct-supers (list SUPER)
    'direct-slots (list 'SLOT1 'SLOT2)) )

Note that slots-names are not required to be symbols, so the following is perfectly valid:

(define hidden-slot (list 'hidden))
(define <myclass>
  (make <class>
     'direct-supers (list <object>)
     'direct-slots (list hidden-slot) ) )
(define x1 (make <myclass>)
(slot-set! x1 hidden-slot 99)

define-generic

[syntax] (define-generic NAME [CLASS])

Sets the variable NAME to contain a fresh generic function object without associated methods. If the optional argument CLASS is given, then the generic function will be an instance of that class.

define-method

[syntax] (define-method (NAME (VARIABLE1 CLASS1) ... PARAMETERS ...) BODY ...)

Adds a new method with the code BODY ... to the generic function that was assigned to the variable NAME. CLASS1 ... is a list if classes that specialize this particular method. The method can have additional parameters PARAMETERS, which do not specialize the method any further. Extended lambda-lists are allowed (#!optional, #!key or #!rest argument lists), but can not be specialized. Inside the body of the method the identifier call-next-method names a procedure of zero arguments that can be invoked to call the next applicable method with the same arguments. If no generic function is defined under this name, then a fresh generic function object is created and assigned to NAME.

Note that only define-generic expands into a valid definition, so for internal lexically scoped definitions use define-generic.

Currently methods defined with define-method should not be hidden (via (declare (hide ...)), nor should such files be compiled in block mode, unless the methods are exported.

Base language

add-method

[procedure] (add-method GENERIC METHOD)

Adds the method object METHOD to the list of applicable methods for the generic function GENERIC.

instance?

[procedure] (instance? X)

Returns #t if X is an instance of a non-primitive class.

make

[procedure] (make CLASS INITARG ...)

Creates a new instance of CLASS and passes INITARG ... to the initialize method of this class.

make-class

[procedure] (make-class SUPERCLASSES SLOTNAMES)

Creates a new class object, where SUPERCLASSES should be the list of direct superclass objects and SLOTNAMES should be a list of symbols naming the slots of this class.

make-generic

[procedure] (make-generic [NAME])

Creates a new generic function object. If NAME is specified, then it should be a string.

make-method

[procedure] (make-method SPECIALIZERS PROC)

Creates a new method object specialized to the list of classes in SPECIALIZERS.

(define-method (foo (x <bar>)) 123)
   <=> (add-method foo
                   (make-method
                      (list <bar>)
                      (lambda (call-next-method x) 123)))

slot-ref

[procedure] (slot-ref INSTANCE SLOTNAME)

Returns the value of the slot SLOTNAME of the object INSTANCE.

slot-set!

[procedure] (slot-set! INSTANCE SLOTNAME VALUE)
[setter] (set! (slot-ref INSTANCE SLOTNAME) VALUE)

Sets the value of the slot SLOTNAME of the object INSTANCE to VALUE.

slot@

[syntax] (slot@ OBJECT SLOTNAME ... [= VALUE])

Object slots are de-referenced by name left-to-right, with an optional last slot assignment.

(slot@ foo x y)           ;=> (slot-ref (slot-ref foo 'x) 'y)
(slot@ foo x y = "bar")   ;=> (slot-set! (slot-ref foo 'x) 'y "bar")

Introspection

class-cpl

[procedure] (class-cpl CLASS)

Returns the class-precedence-list of CLASS as a list of classes.

class-direct-slots

[procedure] (class-direct-slots CLASS)

Returns the list of direct slots of CLASS as a list of lists, where each sublist contains the name of the slot.

class-direct-supers

[procedure] (class-direct-supers CLASS)

Returns the list of direct superclasses of CLASS.

class-of

[procedure] (class-of X)

Returns the class that the object X is an instance of.

See Extensions below for an API to extend the set of "built-in" classes.

class-name

[procedure] (class-name CLASS)

Returns name of CLASS.

class-slots

[procedure] (class-slots CLASS)

Returns the list of all slots of CLASS and its superclasses as a list of lists, where each sublist contains the name of the slot.

generic-methods

[procedure] (generic-methods GENERIC)

Returns the list of all methods associated with the generic function GENERIC.

method-specializers

[procedure] (method-specializers METHOD)

Returns the list of classes that specialize METHOD.

method-procedure

[procedure] (method-procedure METHOD)

Returns the procedure that contains the body of METHOD.

subclass?

[procedure] (subclass? CLASS1 CLASS2)

Returns #t is CLASS1 is a subclass of CLASS2, or #f otherwise. Note that the following holds:

(subclass? X X) ==> #t

instance-of?

[procedure] (instance-of? X CLASS)

Returns #t if X is an instance of CLASS (or one of its subclasses).

Intercessory protocol

These definitions allow interfacing to the Meta Object Protocol of TinyCLOS. For serious use, it is recommended to consult the source code (tinyclos.scm).

allocate-instance

[generic] (allocate-instance CLASS)

Allocates storage for an instance of CLASS and returns the instance.

compute-apply-generic

[generic] (compute-apply-generic GENERIC)

Returns a procedure that will be called to apply the generic function methods to the arguments.

compute-apply-methods

[generic] (compute-apply-methods GENERIC)

Returns a procedure of two arguments, a list of applicable methods and a list of arguments and applies the methods.

compute-methods

[generic] (compute-methods GENERIC)

Returns a procedure of one argument. The procedure is called with the list of actual arguments passed to the generic function and should return a list of applicable methods, sorted by precedence.

compute-cpl

[generic] (compute-cpl CLASS)

Computes and returns the class-precedence-list of CLASS.

compute-getter-and-setter

[generic] (compute-getter-and-setter CLASS SLOT ALLOCATOR)

Returns two values, the procedures that get and set the contents of the slot SLOT. ALLOCATOR is a procedure of one argument that gets an initializer function and returns the getter and setter procedures for the allocated slot.

compute-method-more-specific?

[generic] (compute-method-more-specific? GENERIC)

Returns a procedure of three arguments (two methods and a list of arguments) that returns #t if the first method is more specific than the second one with respect to the list of arguments. Otherwise the returned predicate returns #f.

compute-slots

[generic] (compute-slots CLASS)

Computes and returns the list of slots of CLASS.

initialize

[generic] (initialize INSTANCE INITARGS)

Initializes the object INSTANCE. INITARGS is the list of initialization arguments that were passed to the make procedure.

Additional protocol

describe-object

[generic] (describe-object INSTANCE [PORT])

Writes a description of INSTANCE to PORT. Execution of the interpreter command ,d will invoke this generic function. If PORT is not given it defaults to the value of (current-output-port).

[generic] (print-object INSTANCE [PORT])

Writes a textual representation of INSTANCE to PORT. Any output of an instance with display, write and print will invoke this generic function. If PORT is not given it defaults to the value of (current-output-port).

Utility procedures

initialize-slots

[procedure] (initialize-slots INSTANCE INITARGS)

This procedure takes a sequence of alternating slot-names and initialization values in INITARGS and initializes the corresponding slots in INSTANCE.

 (define-class <pos> () (x y))
 
 (define-method (initialize (pos <pos>) initargs)
   (call-next-method)
   (initialize-slots pos initargs))
 
 (define p1 (make <pos> 'x 1 'y 2))
 (define p2 (make <pos> 'x 3 'y 5))

make/copy

[procedure] (make/copy INSTANCE [INITARGS])

Returns a copy of the object INSTANCE. INITARGS is the list of initialization arguments that will override the INSTANCE copy slot values.

Builtin classes

The class hierarchy of builtin classes looks like this:

 <top>
   <object>
     <class>
       <procedure-class>
	 <entity-class>
	   <generic>
       <primitive-class>
	 <procedure>
   <c++-object>
   <primitive>
     <void>
     <boolean>
     <symbol>
     <char>
     <vector>
     <pair>
     <number>
       <integer>
        <exact>
       <inexact>
     <string>
     <port>
       <input-port>
       <output-port>
     <pointer>
       <tagged-pointer>
       <swig-pointer>
     <locative>
     <blob>
     <byte-vector> ; DEPRECATED
     <structure>
       <u8vector>
       <s8vector>
       <u16vector>
       <s16vector>
       <u32vector>
       <s32vector>
       <f32vector>
       <f64vector>
       <char-set>
       <condition>
       <continuation>
       <environment>
       <hash-table>
       <lock>
       <mmap>
       <mutex>
       <promise>
       <queue>
       <read-table>
       <regexp>
       <tcp-listener>
       <thread>
       <time>
     <end-of-file>

<primitive>

The parent class of the classes of all primitive Scheme objects.

boolean

symbol

char

vector

null

pair

number

integer

exact

inexact

string

port

environment

end-of-file

input-port

output-port

procedure

The classes of primitive Scheme objects.

byte-vector ; DEPRECATED

blob

structure

hash-table

queue

The classes of extended data types provided by the various library units.

class

The parent class of all class objects.

     

entity-class

The parent class of objects that can be invoked as a procedure and have slots.

generic

The parent class of generic function objects.

method

The parent class of method objects.

object

The parent class of all objects.

procedure-class

The parent class of objects that can be invoked as a procedure.

condition

Class of condition objects.

continuation

Class of continuation objects captured by continuation-capture.

array

char-set

time

u8vector

s8vector

u16vector

s16vector

u32vector

s32vector

f32vector

f64vector

The classes of data objects provided by the various supplied SRFIs.

lock

mmap

Classes of objects used in the posix library unit.

pointer

tagged-pointer

swig-pointer

A machine pointer (untagged, tagged or pointing to SWIG-wrapped data).

     

locative

A locative.

promise

The class of objects returned by delay.

tcp-listener

The class of an object returned by tcp-listen.

regexp

The class of an object returned by regexp.

c++-object

The class of generated wrappers for C++ classes parsed by the "easy" Foreign Function interface easyffi.

Extending class-of

The class-of procedure can be extended to recognize additional classes beyond the builtin set.

define-primitive-class

[syntax] (define-primitive-class NAME PREDICATE [SUPER-CLASS ...])

Defines a new primitive class, <NAME>, with type predicate procedure PREDICATE, and the super-classes SUPER-CLASS .... When a SUPER-CLASS is not specified the class <primitive> is assumed.

The PREDICATE procedure takes the object to test as the lone parameter, and returns #f for failure.

Any existing class with the same PREDICATE will be replaced!


[procedure] (##tinyclos#delete-primitive-class CLASS)

Remove the CLASS from the extended set of primitive classes.

define-structure-class

[syntax] (define-structure-class NAME TAG)

Defines a new structure class, <NAME>, with class-of structure type symbol TAG.

Any existing class with the same TAG will be replaced!

[procedure] (##tinyclos#delete-structure-class CLASS)

Remove the CLASS from the extended set of structure classes.

define-tagged-pointer-class

[syntax] (define-tagged-pointer-class NAME TAG)

Defines a new tagged-pointer class, <NAME>, with class-of tagged-pointer type symbol TAG.

Any existing class with the same TAG will be replaced!

[procedure] (##tinyclos#delete-tagged-pointer-class CLASS)

Remove the CLASS from the extended set of tagged-pointer classes.

define-extended-procedure-class

[syntax] (define-extended-procedure-class NAME PREDICATE)

Defines a new extended-procedure class, <NAME>, with type predicate procedure PREDICATE.

The PREDICATE procedure takes the extended-data to test as the lone parameter, and returns #f for failure.

Any existing class with the same PREDICATE will be replaced!

[procedure] (##tinyclos#delete-extended-procedure-class CLASS)

Remove the CLASS from the extended set of extended-procedure classes.

Authors

Orignal version by Gregor Kiczales, CHICKEN port and performance enhancements by felix winkelmann, some of which have been inspired by Eli Barzilays Swindle

slot@ from the '@' macro by Dan Muresan.

License

Copyright (c) 2000-2007, Felix L. Winkelmann
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
conditions are met:
  Redistributions of source code must retain the above copyright notice, this list of conditions and the following
    disclaimer. 
  Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
    disclaimer in the documentation and/or other materials provided with the distribution. 
  Neither the name of the author nor the names of its contributors may be used to endorse or promote
    products derived from this software without specific prior written permission. 
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

Version History

1.5
fixed use of obsolete reader hack
1.404
added make/copy [Kon Lovett]
1.403
added unbound error to class-of [Kon Lovett]
1.402
fixed bug in class-of that caused crash when passed void [felix winkelmann]
1.401
Uses ':optional' (for older Chicken) [Kon Lovett]
1.4
Added class-of extension api, and slot@. Much internal re-ordering [Kon Lovett]
1.3
removed unnecessary feature-registration [thanks to Matthew Welland]
1.2
removed use of :optional in tinyclos.scm [thanks to Todd Ingalls]
1.1
added missing syntax indicator in setup script
1.0
moved from base distribution into separate extension