From 17d6de847106f8b51e18b94f90492f81abe37e01 Mon Sep 17 00:00:00 2001 From: Chris Hanson Date: Wed, 25 Jun 1997 07:22:56 +0000 Subject: [PATCH] Extensive changes corresponding to new release of SOS that uses generic procedure support provided by the runtime system. --- v7/doc/sos/sos.texinfo | 1942 ++++++++++++++++++++++------------------ 1 file changed, 1068 insertions(+), 874 deletions(-) diff --git a/v7/doc/sos/sos.texinfo b/v7/doc/sos/sos.texinfo index 220755b41..8208499b9 100644 --- a/v7/doc/sos/sos.texinfo +++ b/v7/doc/sos/sos.texinfo @@ -6,15 +6,15 @@ @setchapternewpage odd @synindex vr fn -@c $Id: sos.texinfo,v 1.6 1994/06/01 20:15:23 cph Exp $ +@c $Id: sos.texinfo,v 2.1 1997/06/25 07:22:56 cph Exp $ @set TITLE The SOS Reference Manual -@set EDITION 1.6 -@set UPDATED 1 June 1994 -@set UPDATE-MONTH June 1994 +@set EDITION 2.0 +@set UPDATED 25 June 1997 +@set UPDATE-MONTH June 1997 @ifinfo -Copyright @copyright{} 1993-94 Massachusetts Institute of Technology +Copyright @copyright{} 1993-97 Massachusetts Institute of Technology This is Edition @value{EDITION}, last updated @value{UPDATED}, of @cite{@value{TITLE}}. @@ -63,7 +63,7 @@ literature without prior written consent from MIT in each case. @page @vskip 0pt plus 1filll -Copyright @copyright{} 1993-94 Massachusetts Institute of Technology +Copyright @copyright{} 1993-97 Massachusetts Institute of Technology This material was developed by the Scheme project at the Massachusetts Institute of Technology, Department of Electrical Engineering and Computer @@ -100,6 +100,7 @@ literature without prior written consent from MIT in each case. @end enumerate @end titlepage +@ifinfo @node Top, Object System, (dir), (dir) This is Edition @value{EDITION}, last updated @value{UPDATED}, of @@ -109,117 +110,74 @@ This is Edition @value{EDITION}, last updated @value{UPDATED}, of * Object System:: * Variable Index:: * Concept Index:: - - --- The Detailed Node Listing --- - -The Object System - -* Language:: -* Reflective Operations:: -* Meta-Object Protocol:: -* Miscellany:: - -The Language - -* Classes:: -* Predefined Classes:: -* Instances:: -* Slots:: -* Generic Procedures:: -* Methods:: -* Record Classes:: - -Reflective Operations - -* Class Reflectives:: Reflective Operations on Classes -* Generic Reflectives:: Reflective Operations on Generic Procedures -* Method Reflectives:: Reflective Operations on Methods -* Slot Reflectives:: Reflective Operations on Slots - -The Meta-Object Protocol - -* Generic Invocation Subprotocol:: -* Instantiation Subprotocol:: -* Class Initialization Subprotocol:: @end menu +@end ifinfo @node Object System, Variable Index, Top, Top -@chapter The Object System +@chapter An Object System @sc{sos} is a Scheme @dfn{object system} derived from Tiny @sc{clos} @footnote{Tiny @sc{clos} was written by Gregor Kiczales of Xerox @sc{parc}; @sc{sos} is derived from version 1.2 of Tiny @sc{clos}.}, which in turn was loosely derived from @sc{clos}, the Common Lisp Object System. Its basic design and philosophy is closely related to Tiny -@sc{clos}, but there are differences in naming, interface, and in the -meta-object protocol. +@sc{clos}, but there are differences in naming and interface. + +This document is a reference manual, and as such does not attempt to +teach the reader about object-oriented programming. It is assumed that +you already have a passing familiarity with @sc{clos} and with Scheme. In the procedure descriptions that follow, certain argument names imply -restrictions on the corresponding argument: +restrictions on the corresponding argument. Here is a table of those +names. The parenthesised name in each entry is the name of the +predicate procedure that the argument must satisfy. @table @var @item class -The argument must be a @dfn{class}, i.e.@: it must satisfy the predicate -@code{class?}. +The argument must be a @dfn{class} (@code{class?}). @item instance -The argument must be an @dfn{instance}, i.e.@: it must satisfy the -predicate @code{instance?}. +The argument must be an @dfn{instance} (@code{instance?}). @item name -The argument must be a symbol. +The argument must be a symbol (@code{symbol?}); sometimes this is also +allowed to be @code{#f} (@code{false?}). @item generic-procedure -The argument must be a @dfn{generic procedure}, i.e.@: it must satisfy -the predicate @code{generic-procedure?}. - -@item generic -The argument must be a @dfn{generic procedure instance}, i.e.@: it must -satisfy the predicate @code{(lambda (x) (instance-of? x ))}. +The argument must be a @dfn{generic procedure} +(@code{generic-procedure?}). @item method -The argument must be a @dfn{method}, i.e.@: it must satisfy the -predicate @code{(lambda (x) (instance-of? x ))}. +The argument must be a @dfn{method} (@code{method?}). + +@item specializer +The argument must be a @dfn{method specializer} (@code{specializer?}). @item procedure -The argument must be a procedure. +The argument must be a procedure (@code{procedure?}). @item slot -The argument must be a @dfn{slot descriptor}, i.e.@: it must satisfy the -predicate @code{slot?}. - -@item plist -The argument must be a @dfn{property list}, i.e.@: it must be a list of -even length, the even-numbered elements of which must be symbols. +The argument must be a @dfn{slot descriptor} (@code{slot-descriptor?}). @end table -@menu -* Language:: -* Reflective Operations:: -* Meta-Object Protocol:: -* Miscellany:: -@end menu - -@node Language, Reflective Operations, , Object System -@section The Language - @menu * Classes:: -* Predefined Classes:: * Instances:: * Slots:: * Generic Procedures:: * Methods:: -* Record Classes:: +* Printing:: @end menu -@node Classes, Predefined Classes, , Language -@subsection Classes +@node Classes, Instances, Object System, Object System +@section Classes @cindex class @cindex instance A @dfn{class} is an object that determines the structure and behavior of -a set of other objects, which are called its @dfn{instances}. +a set of other objects, which are called its @dfn{instances}. However, +in this document, the word @dfn{instance} usually means an instance of +the class @code{}. @cindex subclass @cindex superclass @@ -266,7 +224,7 @@ to order methods from most specific to least specific. @cindex local precedence order @cindex precedence order, local @cindex order, local precedence -When a class is defined, the order in which its direct superclasse are +When a class is defined, the order in which its direct superclasses are mentioned in the defining form is important. Each class has a @dfn{local precedence order}, which is a list consisting of the class followed by its direct superclasses in the order mentioned in the @@ -281,59 +239,24 @@ precedence list can be constructed, and an error is signalled. Classes are organized into a @dfn{directed acyclic graph}. There are two distinguished classes, named @code{} and @code{}. The class named @code{} has no superclasses. It is a superclass -of every class except itself. The class named @code{} is an -instance of the class @code{} and is a superclass of every class -that is an instance of @code{} except itself. - -@cindex metaclass -Classes are represented by objects that are themselves instances of -classes. The class of the class of an object is termed the -@dfn{metaclass} of that object. When no misinterpretation is possible, -the term @dfn{metaclass} will be used to refer to a class that has -instances that are themselves classes. The metaclass determines the -form of the instances of those classes. @sc{sos} provides a default -metaclass, @code{}, that is appropriate for most programs. The -meta-object protocol provides mechanisms for defining and using new -metaclasses. - -Except where otherwise specified, all classes mentioned in this chapter -are instances of the class @code{}, all generic procedures are -instances of the class @code{}, and all methods are -instances of the class @code{}. - -@deffn Syntax define-class name direct-superclasses direct-slot @dots{} -Define @var{name} to be a class. In its basic form, @code{define-class} -might have been defined by +of every class except itself. The class named @code{} is a +direct subclass of @code{} and is the base class for +@dfn{instance} objects. Instances are special because @sc{sos} has +efficient mechanisms for dispatching on them and for accessing their +slots. -@lisp -(define-syntax define-class - (syntax-rules () - ((define-class name (class ...) slot ...) - (define name - (make-class (quote name) - (list class ...) - (quote (slot ...))))))) -@end lisp - -Note that slot options are handled specially by @code{define-class}. If -a @var{direct-slot} specifies a slot options property list, the keys of -the property list (i.e.@: the even-numbered elements) are not evaluated, -while the datums of the property list @emph{are} evaluated. The -expansion above does not show the proper treatment of slot options. +@menu +* Class Datatype:: +* Predefined Classes:: +* Record Classes:: +* Specializers:: +@end menu -@cindex class options -@code{define-class} permits the specification of @dfn{class options}, -which are options that pertain to the class as a whole. Class options -are specified by overloading @var{name}: instead of a symbol, specify a -pair whose @sc{car} is a symbol and whose @sc{cdr} is an alist. At -present only one class option is recognized: +@node Class Datatype, Predefined Classes, Classes, Classes +@subsection Class Datatype -@table @code -@item (metaclass @var{class}) -Specifies that @var{class} is the metaclass of the class being defined. -If this option is not given, the metaclass defaults to @code{}. -@end table -@end deffn +The procedures in this section may be used to construct and inspect +classes. @deffn Procedure make-class name direct-superclasses direct-slots Creates and returns a new class object. @@ -364,21 +287,21 @@ first of these two forms is equivalent to the second with an empty Each of the elements of @var{direct-slots} defines one slot named @var{name}. @var{Plist} is used to describe additional properties of -that slot. The meaning of @var{plist} is defined by -@code{compute-slot-descriptor}; by default these properties are -recognized: +that slot. The following properties are recognized: @table @code -@item initializer -A procedure of no arguments that is called (by @code{allocate-instance}) -whenever an instance containing this slot is created. The value -returned by the procedure is the initial value of the slot. If the -@code{initializer} property is not specified, or if it is specified as -@code{#f}, the slot is not initialized. +@item initial-value +This property specifies the default initial value for the slot, i.e.@: +the value stored in the slot when an instance is created and no value is +explicitly specified by the instance constructor. If neither the +@code{initial-value} nor the @code{initializer} property is specified, +the slot has no default initial value. -The use of the @code{initializer} is automatic if the slot has an -@code{allocation} of @code{instance}; otherwise the meta-object protocol -must invoke @code{initializer} and use its value to initialize the slot. +@item initializer +This property specifies a procedure of no arguments that is called by an +instance constructor whenever an instance containing this slot is +created. The value returned by the @code{initializer} procedure is the +initial value of the slot. @item accessor This property specifies a generic procedure; @code{make-class} will add @@ -392,21 +315,199 @@ a modifier method for this slot to the procedure. @xref{Slots}. This property specifies a generic procedure; @code{make-class} will add an ``initialized?''@: predicate method for this slot to the procedure. @xref{Slots}. +@end table + +Slot properties are combined in slightly complicated ways. + +@itemize @bullet +@item +It is not allowed to specify both @code{initial-value} and +@code{initializer} for a slot in a given call to @code{make-class}; at +most one of these properties may be given. + +@item +If a slot is specified for a given class, and a slot of the same name is +inherited from a superclass, then the slot properties for the two slots +are combined. Slot properties from the subclass shadow those of the +superclass. However, if a superclass has a slot property, and the +subclass does not, the property is inherited. The resulting class never +has more than one slot of a given name. + +@item +When combining superclass and subclass slots, @code{initial-value} and +@code{initializer} shadow one another. In other words, regardless of +the inherited slot properties, the resulting slot has at most one of +these two properties. +@end itemize + +Examples of @code{make-class}: -@item allocation -A symbol describing how the slot should be allocated. If the -@code{allocation} property is the symbol @code{instance}, or if it is -not specified, then the slot is an ordinary instance slot. Otherwise -the slot is a virtual slot and the meaning of the symbol is defined by -the virtual slot protocol. +@lisp +@group +(define + (make-class ' '() '())) +@end group + +@group +(define + (make-class ' + (list ) + `((name accessor ,cell-name)))) +@end group + +@group +(define + (make-class ' + (list ) + `((width accessor ,cell-width) + (height accessor ,cell-height) + (components accessor ,cell-components + modifier ,set-cell-components! + initial-value ())))) +@end group +@end lisp +@end deffn + +@deffn Syntax define-class name direct-superclasses direct-slot @dots{} +Define @var{name} to be a class. In its basic form, @code{define-class} +might have been defined by + +@lisp +@group +(define-syntax define-class + (syntax-rules () + ((define-class name (class ...) slot ...) + (define name + (make-class (quote name) + (list class ...) + (quote (slot ...))))))) +@end group +@end lisp + +Note that slot properties are handled specially by @code{define-class}. +If a @var{direct-slot} specifies a slot properties property list, the +keys of the property list (i.e.@: the even-numbered elements) are not +evaluated, while the datums of the property list @emph{are} evaluated. +The expansion above does not show the proper treatment of slot +properties. + +In addition to the slot properties recognized by @code{make-class}, +@code{define-class} recognizes a special slot property, called +@code{define}. The @code{define} property specifies that some or all of +the slot accessors should be defined here; that is, generic procedures +should be constructed and bound to variables, and then the accessor +methods added to them. + +The argument to the @code{define} property is a list containing any +combination of the symbols @code{accessor}, @code{modifier}, and +@code{initpred}. As an abbreviation, the argument may be one of these +symbols by itself, which is equivalent to the list containing that +symbol. Also, the argument may be the symbol @code{standard}, which is +equivalent to @code{(accessor modifier)}. + +The argument to @code{define} specifies which accessors will be defined +by this form. The accessors are defined using default names, unless the +names are overridden by the corresponding slot property. The default +names for a class @code{} and a slot @code{bar} are @code{foo-bar}, +@code{set-foo-bar!}, and @code{foo-bar-initialized?}, respectively for +the accessor, modifier, and initpred. For example, + +@lisp +@group +(define-class foo + (bar define accessor)) +@end group +@end lisp + +@noindent +defines an accessor called @code{foo-bar}, but + +@lisp +@group +(define-class foo + (bar define accessor accessor foo/bar)) +@end group +@end lisp + +@noindent +instead defines an accessor called @code{foo/bar}. Finally, + +@lisp +@group +(define-class foo + (bar accessor foo/bar)) +@end group +@end lisp + +@noindent +doesn't define any accessor, but assumes that @code{foo/bar} is a +previously-defined generic procedure and adds an accessor method to it. + +@cindex class options +@code{define-class} permits the specification of @dfn{class options}, +which are options that pertain to the class as a whole. Class options +are specified by overloading @var{name}: instead of a symbol, specify a +pair whose @sc{car} is a symbol and whose @sc{cdr} is an alist. The +following class options are recognized: + +@table @code +@item (predicate @var{[name]}) +Specifies that a predicate procedure should be defined for this class. +@var{Name} must be either a symbol or @code{#f}: a symbol specifies the +name that will be bound to the predicate procedure, and @code{#f} +specifies that no predicate procedure should be defined. If @var{name} +is omitted, or if no @code{predicate} option is specified, a predicate +procedure is defined by appending @code{?} to the name of the class. If +the class name is surrounded by angle brackets, they are stripped off +first. For example, the default predicate name for the class +@code{} is @code{foo?}. + +@item (constructor @var{[name]} @var{slot-names} @var{[n-init-args]}) +Specifies that a constructor procedure should be defined for this class. +@var{Name} must be a symbol, which is the name that will be bound to the +predicate procedure; if omitted, a default name is formed by prepending +@code{make-} to the name of the class. If the class name is surrounded +by angle brackets, they are stripped off first. For example, the +default constructor name for the class @code{} is @code{make-foo}. + +@var{Slot-names} and @var{n-init-args} correspond to the arguments of +the respective names accepted by @code{instance-constructor}, and can +take any of the allowed forms for those arguments. @end table -Please note that the following are equivalent, although the former is -slightly faster: +Examples of @code{define-class} (compare these to the similar examples +for @code{make-class}): + +@lisp +(define-class ()) + +@group +(define-class ( (constructor (name) no-init)) () + (name accessor cell-name)) +@end group + +@group +(define-class ( (constructor ())) () + (width accessor cell-width) + (height accessor cell-height) + (components accessor cell-components + modifier set-cell-components! + initial-value '())) +@end group +@end lisp +@end deffn + +@deffn Procedure make-trivial-subclass superclass1 superclass2 @dots{} +This convenience procedure makes a subclass that defines no new slots, +and that inherits from the given superclasses. It is equivalent to the +following @lisp -(make-class @var{name} @var{superclasses} @var{slots}) -(make-instance @var{name} @var{superclasses} @var{slots}) +@group +(make-class (class-name @var{superclass1}) + (list @var{superclass1} @var{superclass2} @dots{}) + '()) +@end group @end lisp @end deffn @@ -415,23 +516,61 @@ Returns @code{#t} if @var{object} is a class, otherwise returns @code{#f}. @end deffn +@deffn Procedure subclass? class specializer +Returns @code{#t} if @var{class} is a subclass of @var{specializer}, +otherwise returns @code{#f}. If @var{specializer} is a class, the +result follows from the above definition of subclass, except that a +class is a subclass of itself. If @var{specializer} is a record type, +it is equivalent to having used the @code{record-type-class} of the +record type. Finally, if @var{specializer} is a union specializer, +@code{subclass?} is true if @var{class} is a subclass of one or more of +the component classes of @var{specializer}. +@end deffn + @deffn Procedure object-class object Returns the class of @var{object}. @var{Object} may be any Scheme -object; if @var{object} is known to be an instance, it is better to use -@code{instance-class} rather than @code{object-class}. +object; if @var{object} is known to be an instance, +@code{instance-class} is faster than @code{object-class}. @end deffn -@deffn Procedure instance-class instance -Returns the class of @var{instance}. +@deffn Procedure class-name class +Returns the name of @var{class}. This is the @var{name} argument passed +to @code{make-class} when @var{class} was created. +@end deffn + +@deffn Procedure class-direct-superclasses class +Returns a list of the direct superclasses of @var{class}. If a +non-empty @var{direct-superclasses} argument was passed to +@code{make-class} when @var{class} was created, this list is +@code{equal?} to that argument. The returned value must not be +modified. +@end deffn + +@deffn Procedure class-direct-slot-names class +Returns a list of symbols that are the names of the direct slots of +@var{class}. This list contains only those slots that were defined in +the call to @code{make-class} that created @var{class}; it does not +contain slots that were inherited. The returned value must not be +modified. +@end deffn + +@deffn Procedure class-precedence-list class +Returns a list of the superclasses of @var{class}. The order of this +list is significant: it is the method resolution order. This list will +always have @var{class} as its first element, and @code{} as its +last element. The returned value must not be modified. @end deffn -@node Predefined Classes, Instances, Classes, Language +@node Predefined Classes, Record Classes, Class Datatype, Classes @subsection Predefined Classes +@cindex predefined classes +@sc{sos} provides a rich set of predefined classes that can be used to +specialize methods to any of Scheme's built-in datatypes. + @defvr Class This is the class of all Scheme objects. It has no direct superclasses, -and all other classes are subclasses of this class. This class is an -instance of the class @code{}. +and all other classes are subclasses of this class. @end defvr @defvr Class @@ -440,26 +579,12 @@ This is the class of instances. It is a direct subclass of the predicate @code{instance?}. @end defvr -@defvr Class -This is the class of classes. It is a direct subclass of -@code{}. The members of this class are the objects that -satisfy the predicate @code{class?}. -@end defvr - -@defvr Class -This is the class of generic procedure instances. It is a direct -subclass of @code{}. -@end defvr - -@defvr Class -This is the class of method objects. It is a direct subclass of -@code{}. -@end defvr - @defvr Class @defvrx Class +@defvrx Class @defvrx Class @defvrx Class +@defvrx Class @defvrx Class @defvrx Class @defvrx Class @@ -467,18 +592,24 @@ These are the classes of their respective Scheme objects. They are all direct subclasses of @code{}. The members of each class are the objects that satisfy the corresponding predicate; for example, the members of @code{} are the objects that satisfy -@code{procedure?}. These classes are instances of the class -@code{}, except for @code{} which is an -instance of @code{}. +@code{procedure?}. +@end defvr + +@defvr Class +This is the class of generic procedure instances. It is a direct +subclass of @code{}. +@end defvr + +@defvr Class +This is the class of method objects. It is a direct subclass of +@code{}. @end defvr -@defvr Class -This is the class of mathematical objects. It is a direct subclass of -@code{}. This class is an abstract class; @code{object-class} -will not return this class for any object. This class exists in order -to contain other kinds of mathematical objects besides numbers, in those -implementations that provide them. For example, the objects defined by -the @sc{scmutils} algebra system are subclasses of this class. +@defvr Class +@defvrx Class +@defvrx Class +These classes specify additional method objects with special properties. +Each class is a subclass of @code{}. @end defvr The following are the classes of Scheme numbers. Note that @@ -496,8 +627,7 @@ so you should use these classes for specialization. These are the classes of the Scheme numeric tower. @code{} is a direct subclass of @code{}, @code{} is a direct subclass of @code{}, @code{} is a direct subclass of -@code{}, etc. These classes are instances of the class -@code{}. +@code{}, etc. @end defvr @defvr Class @@ -509,8 +639,7 @@ These are the classes of exact numbers. @code{} is a direct subclass of @code{}, @code{} is a direct subclass of @code{} and @code{}, and in general, each is a direct subclass of preceding class and of the class without the -@code{exact-} prefix. These classes are instances of the class -@code{}. +@code{exact-} prefix. @end defvr @defvr Class @@ -522,79 +651,202 @@ These are the classes of inexact numbers. @code{} is a direct subclass of @code{}, @code{} is a direct subclass of @code{} and @code{}, and in general, each is a direct subclass of preceding class and of the class without the -@code{inexact-} prefix. These classes are instances of the class -@code{}. +@code{inexact-} prefix. @end defvr -@defvr Class -This is the class of entity objects. It is a direct subclass of -@code{}. This class is an instance of the class -@code{}. +@node Record Classes, Specializers, Predefined Classes, Classes +@subsection Record Classes -This class is defined only in implementations that support entities. -@end defvr +@cindex record class +@sc{sos} allows generic procedures to discriminate on record types. +This means that a record structure defined by means of +@code{make-record-type} or @code{define-structure} can be passed as an +argument to a generic procedure, and the generic procedure can use the +record's type to determine which method to be invoked.@footnote{If the +@code{type} option of @code{define-structure} is used, the resulting +data structure is @emph{not} a record and thus cannot be used in this +manner.} + +In order to support this, @sc{sos} accepts record type descriptors in +all contexts that accept classes. Additionally, every record type +descriptor has an associated @sc{sos} class; either the class or the +record type can be used with equivalent results. -@defvr Class -This is the class of record objects. It is a direct subclass of -@code{}. This class is an instance of the class -@code{}. +@deffn Procedure record-type-class record-type +@var{Record-type} must be a record type descriptor (in other words, it +must satisfy the predicate @code{record-type?}). Returns the class +associated with @var{record-type}. +@end deffn -This class is defined only in implementations that support an opaque -record type. -@end defvr +@deffn Procedure record-class record +@var{Record} must be a record (in other words, it must satisfy the +predicate @code{record?}). Returns the class associated with +@var{record}. This is equivalent to -@node Instances, Slots, Predefined Classes, Language -@subsection Instances +@lisp +(record-type-class (record-type-descriptor @var{record})) +@end lisp +@end deffn -@deffn Procedure make-instance class initarg @dots{} -Creates and returns a new instance of @var{class}. +@node Specializers, , Record Classes, Classes +@subsection Specializers -The instance is created by a two-step process, which is described here -to explain the meaning of the @var{initarg}s. +@cindex specializer +A @dfn{specializer} is a generalization of a class. A specializer is +any one of the following: -@enumerate +@itemize @bullet @item -@code{allocate-instance} is called with @var{class} as its argument to -allocate a new instance. +A class. @item -@code{initialize-instance} is called with the new instance and the -@var{initarg}s as its arguments. -@end enumerate +A record type, which is equivalent to its associated class. -@noindent -In other words, @code{make-instance} might be defined by +@item +A union specializer, which is a set of classes. +@end itemize -@lisp -(define (make-instance class . initargs) - (let ((instance (allocate-instance class))) - (apply initialize-instance instance initargs) - instance)) -@end lisp +A specializer may be used in many contexts where a class is required, +specifically, as a method specializer (hence the name), as the second +argument to @code{subclass?}, and elsewhere. + +@deffn Procedure specializer? object +Returns @code{#t} if @var{object} is a specializer, otherwise returns +@code{#f}. +@end deffn + +@deffn Procedure specializer-classes specializer +Returns a list of the classes in @var{specializer}. If +@var{specializer} is a class, the result is a list of that class. If +@var{specializer} is a record type, the result is a list of the record +type's class. If @var{specializer} is a union specializer, the result +is a list of the component classes of the specializer. +@end deffn + +@deffn Procedure specializer=? specializer1 specializer2 +Returns @code{#t} if @var{specializer1} and @var{specializer2} are +equivalent, otherwise returns @code{#f}. Two specializers are +equivalent if the lists returned by @code{specializer-classes} contain +the same elements. +@end deffn + +@deffn Procedure union-specializer specializer @dots{} +Returns a union specializer consisting of the union of the classes of +the arguments. This is equivalent to converting all of the specializer +arguments to sets of classes, then taking the union of those sets. +@end deffn + +@deffn Procedure union-specializer? object +Returns @code{#t} if @var{object} is a union specializer, otherwise +returns @code{#f}. +@end deffn -Note that the meaning of the @var{initarg}s is completely determined by -@code{initialize-instance}. The default method for -@code{initialize-instance} does not accept any @var{initarg}s; if you -want to pass @var{initarg}s when creating an instance, you must define a -method on @code{initialize-instance} to accept them. +@deffn Procedure specializers? object +Returns @code{#t} if @var{object} is a list of specializers, otherwise +returns @code{#f}. +@end deffn + +@deffn Procedure specializers=? specializers1 specializers2 +@var{Specializers1} and @var{specializers2} must be lists of +specializers. Returns @code{#t} if @var{specializers1} and +@var{specializers2} are equivalent, otherwise returns @code{#f}. +Two specializers lists are equivalent if each of their corresponding +elements is equivalent. +@end deffn -Here is an example showing how this is done: +@node Instances, Slots, Classes, Object System +@section Instances + +@cindex instance +An @dfn{instance} is a compound data structure much like a record, +except that it is defined by a class rather than a record type +descriptor. Instances are more powerful than records, because their +representation is designed to support inheritance, while the +representation of records is not. + +@deffn Procedure instance-constructor class slot-names [n-init-args] +Creates and returns a procedure that, when called, will create and +return a newly allocated instance of @var{class}. + +@var{Class} must be a subclass of @code{}. @var{Slot-names} +must be a list of symbols, each of which must be the name of a slot in +@var{class}. @var{N-init-args} will be described below. + +In its basic operation, @code{instance-constructor} works much like +@code{record-constructor}: the @var{slot-names} argument specifies how +many arguments the returned constructor accepts, and each of those +arguments is stored in the corresponding slot of the returned instance. +Any slots that are not specified in @var{slot-names} are given their +initial values, as specified by the @code{initial-value} or +@code{initializer} slot properties; otherwise they are left +uninitialized. + +@cindex initialize-instance +@findex initialize-instance +After the new instance is created and its slots filled in, but before it +is returned, it is passed to the generic procedure +@code{initialize-instance}. Normally, @code{initialize-instance} does +nothing, but because it is always called, the programmer can add methods +to it to specify an initialization that is to be performed on every +instance of the class. + +By default, @code{initialize-instance} is called with one argument, the +newly created instance. However, the optional argument +@var{n-init-args} can be used to specify additional arguments that will +be passed to @code{initialize-instance}. + +The way this works is that the returned constructor procedure accepts +additional arguments after the specified number of slot values, and +passes these extra arguments to @code{initialize-instance}. When +@var{n-init-args} is not supplied or is @code{#t}, any number of extra +arguments are accepted and passed along. When @var{n-init-args} is an +exact non-negative integer, exactly that number of extra arguments must +be supplied when the constructor is called. Finally, if +@var{n-init-args} is the symbol @code{no-initialize-instance}, then the +constructor accepts no extra arguments and does not call +@code{initialize-instance} at all; this is desirable when +@code{initialize-instance} is not needed, because it makes the +constructor significantly faster. + +For notational convenience, @var{n-init-args} may take two other forms. +First, it may be a list of symbols, which is equivalent to the integer +that is the length of the list. Second, it may be the symbol +@code{no-init}, which is an abbreviation for +@code{no-initialize-instance}. + +Note that the default method on @code{initialize-instance} accepts no +extra arguments and does nothing. + +Examples of @code{instance-constructor}: @lisp -(define-class () - x - y) +@group +(define-class () + (from accessor reference-from) + (to accessor reference-to) + (cx accessor reference-cx) + (cy accessor reference-cy)) +@end group -(define position-x (slot-accessor 'x)) -(define position-y (slot-accessor 'y)) -(define set-position-x! (slot-modifier 'x)) -(define set-position-y! (slot-modifier 'y)) +@group +(define make-simple-reference + (instance-constructor + '(from to cx cy) + 'no-init)) +@end group -(define-method initialize-instance ((position ) x y) - (set-position-x! position x) - (set-position-y! position y)) +@group +(define-class () + (cell accessor wirenet-cell) + (wires accessor wirenet-wires + modifier set-wirenet-wires! + initial-value '())) +@end group -(make-instance 3.0 5.3) +@group +(define make-simple-wirenet + (instance-constructor '(cell))) +@end group @end lisp @end deffn @@ -603,199 +855,306 @@ Returns @code{#t} if @var{object} is an instance, otherwise returns @code{#f}. @end deffn -@deffn Procedure instance-of? object class -Returns @code{#t} if @var{object} is a general instance of @var{class}, -otherwise returns @code{#f}. In other words, this predicate is true if -the class of @var{object} is @var{class} or one of its subclasses. +@deffn Procedure instance-class instance +Returns the class of @var{instance}. This is faster than +@code{object-class}, but it works only for instances, and not for other +objects. +@end deffn + +@deffn Procedure instance-of? object specializer +Returns @code{#t} if @var{object} is a general instance of +@var{specializer}, otherwise returns @code{#f}. This is equivalent to + +@lisp +(subclass? (object-class @var{object}) @var{specializer}) +@end lisp +@end deffn + +@deffn Procedure instance-predicate specializer +Returns a predicate procedure for @var{specializer}. The returned +procedure accepts one argument and returns @code{#t} if the argument is +an instance of @var{specializer} and @code{#f} otherwise. @end deffn -@node Slots, Generic Procedures, Instances, Language -@subsection Slots -@cindex slots +@node Slots, Generic Procedures, Instances, Object System +@section Slots -An object that has @code{} as its metaclass has zero or more -named slots. The slots of an object are determined by the class of the -object. Each slot can hold one value. The name of a slot is a symbol. +@cindex slot +An instance has zero or more named slots; the name of a slot is a +symbol. The slots of an instance are determined by its class. @cindex uninitialized slot @cindex slot, uninitialized -When a slot does not have a value, the slot is said to be -@dfn{uninitialized}. The default initial value for a slot is defined by -the @code{initializer} slot option. - -@cindex instance slot -@cindex slot, instance -An @dfn{instance slot} is defined to be a slot that is visible to -exactly one instance, namely the one in which the slot is allocated. -The @code{allocation} slot option to @code{make-class} controls the kind -of slot that is defined. If the value of the @code{allocation} slot -option is @code{instance}, an instance slot is created. +Each slot can hold one value. When a slot does not have a value, the +slot is said to be @dfn{uninitialized}. The default initial value for a +slot is defined by the @code{initial-value} and @code{initializer} slot +properties. @cindex accessibility of slots A slot is said to be @dfn{accessible} in an instance of a class if the slot is defined by the class of the instance or is inherited from a superclass of that class. At most one slot of a given name can be -accessible in an instance. +accessible in an instance. Slots are accessed by means of slot-access +methods (usually generated by @code{make-class}). -Slots can be accessed in two ways: by use of the primitive slot-access -procedures @code{slot-accessor}, @code{slot-modifier}, -@code{slot-initpred}, @code{slot-value}, @code{set-slot-value!}, and -@code{slot-initialized?}; and by use of slot-access methods (usually -generated by @code{make-class}). - -The primitive slot-access procedures can be used with any slot name -specified in the call to @code{make-class} to access a specific slot -accessible in an instance of the given class. +@menu +* Slot Descriptors:: +* Slot Access Methods:: +* Slot Access Constructors:: +* Slot Access Procedures:: +@end menu -@cindex accessor, for slot -@cindex slot accessor -@cindex modifier, for slot -@cindex slot modifier -The procedure @code{make-class} provides slot options for generating -methods to read and write slots. If an @dfn{accessor} is requested, a -method is automatically generated for reading the value of the slot. If -a @dfn{modifier} is requested, a method is automatically generated for -storing a value into the slot. When an accessor or modifier is -specified for a slot, the generic procedure to which the generated -method belongs is directly specified. The procedure specified for the -accessor takes one argument, the instance. The procedure specified for -the modifier takes two arguments, the instance and the new value, in -that order. +@node Slot Descriptors, Slot Access Methods, Slots, Slots +@subsection Slot Descriptors -Slot-access methods can also be generated by the procedures -@code{slot-accessor-method}, @code{slot-modifier-method}, and -@code{slot-initpred-method}. These methods may be added to a generic -procedure by passing them as arguments to @code{add-method}. The methods -generated by these procedures are identical to those generated by the -options to @code{make-class}. +@cindex slot descriptor +Slots are represented by @dfn{slot descriptors}, which are data +structures providing information about the slots, such as their name. +Slot descriptors are stored inside of classes, and may be retrieved from +there and subsequently inspected. -Note that @code{slot-value}, @code{set-slot-value!}, and -@code{slot-initialized?} should not be used in most code, as they are -inherently slower than the other slot access mechanisms. +@deffn Procedure class-slots class +Returns a list of the slot descriptors for @var{class}. This contains +all slots for @var{class}, both direct slots and inherited slots. The +returned value must not be modified. +@end deffn -To clarify the relationships between the various access mechanisms, here -are implementations of @code{slot-accessor-method} and -@code{slot-value}, both in terms of @code{slot-accessor}. These -implementations are semantically correct, but do not accurately depict -performance. +@deffn Procedure class-slot class name error? +Returns the slot descriptor for the slot named @var{name} in +@var{class}. If there is no such slot: if @var{error?} is @code{#f}, +returns @code{#f}, otherwise signals an error of type +@code{condition-type:no-such-slot}. +@end deffn -@lisp -@group -(define (slot-accessor-method class name) - (make-leaf-method (list class) (slot-accessor class name))) +@deffn Procedure slot-descriptor? object +Returns @code{#t} if @var{object} is a slot descriptor, otherwise +returns @code{#f}. +@end deffn -(define (slot-value instance name) - ((slot-accessor name) instance)) -@end group -@end lisp +@deffn Procedure slot-name slot +Returns the name of @var{slot}. +@end deffn -@deffn Procedure slot-accessor class name -Returns a procedure of one argument which is an accessor for the slot -@var{name} in @var{class}; @var{name} may be either a symbol or a slot -descriptor. The argument to the returned procedure must be an instance -of @var{class}. When the procedure is called, it returns the contents -of the slot @var{name} in that instance. If the given instance does not -have a slot of that name, or if the slot is not initialized, an error is -signalled. +@deffn Procedure slot-class slot +Returns the class of @var{slot}. This is the class with which +@var{slot} is associated. This is not necessarily the class that +defines @var{slot}; it could also be a subclass of that class. If the +slot was returned from @code{class-slots} or @code{class-slot}, then +this class is the argument passed to that procedure. @end deffn -@deffn Procedure slot-modifier class name -Returns a procedure of two arguments which is a modifier for the slot -@var{name} in @var{class}; @var{name} may be either a symbol or a slot -descriptor. The first argument to the returned procedure must be an -instance of @var{class}, and the second argument may be any object. -When the procedure is called, it modifies the slot @var{name} in the -instance to contain the second argument. If the given instance does not -have a slot of that name, an error is signalled. +@deffn Procedure slot-properties slot +Returns an alist of the properties of @var{slot}. This list must not be +modified. @end deffn -@deffn Procedure slot-initpred class name -Returns a procedure of one argument which is an ``initialized?''@: -predicate for the slot @var{name} in @var{class}; @var{name} may be -either a symbol or a slot descriptor. The argument to the returned -procedure must be an instance of @var{class}. When the procedure is -called, it returns @code{#t} if the slot @var{name} in that instance is -initialized, otherwise it returns @code{#f}. If the given instance does -not have a slot of that name, an error is signalled. +@deffn Procedure slot-property slot name default +If @var{slot} has a property named @var{name}, it is returned; otherwise +@var{default} is returned. +@end deffn + +@deffn Procedure slot-initial-value? slot +Returns @code{#t} if @var{slot} has an initial value, and @code{#f} +otherwise. The initial value is specified by the @code{initial-value} +slot property when a class is made. +@end deffn + +@deffn Procedure slot-initial-value slot +Returns the initial value for @var{slot}, if it has one; otherwise it +returns an unspecified value. The initial value is specified by the +@code{initial-value} slot property when a class is made. @end deffn +@deffn Procedure slot-initializer slot +Returns the initializer for @var{slot}; the initializer is specified by +the @code{initializer} slot property when a class is made. This is a +procedure of no arguments that is called to produce an initial value for +@var{slot}. The result may also be @code{#f} meaning that the slot has +no initializer. +@end deffn + +@node Slot Access Methods, Slot Access Constructors, Slot Descriptors, Slots +@subsection Slot Access Methods + +@cindex accessor, for slot +@cindex slot accessor +@cindex modifier, for slot +@cindex slot modifier +The procedure @code{make-class} provides slot properties that generate +methods to read and write slots. If an @dfn{accessor} is requested, a +method is automatically generated for reading the value of the slot. If +a @dfn{modifier} is requested, a method is automatically generated for +storing a value into the slot. When an accessor or modifier is +specified for a slot, the generic procedure to which the generated +method belongs is directly specified. The procedure specified for the +accessor takes one argument, the instance. The procedure specified for +the modifier takes two arguments, the instance and the new value, in +that order. + +All of the procedures described here signal an error of type +@code{condition-type:no-such-slot} if the given class or object does not +have a slot of the given name. + +Slot-access methods can be generated by the procedures +@code{slot-accessor-method}, @code{slot-modifier-method}, and +@code{slot-initpred-method}. These methods may be added to a generic +procedure by passing them as arguments to @code{add-method}. The +methods generated by these procedures are equivalent to those generated +by the slot properties in @code{make-class}. + @deffn Procedure slot-accessor-method class name -Returns an accessor method for the slot @var{name} in @var{class}. This -method has one required argument, an instance of @var{class}, and the -specializer for that argument is @var{class}. When invoked, the method -returns the contents of the slot specified by @var{name} in the -instance. However, if that slot is not initialized, an error is -signalled instead. +Returns an accessor method for the slot @var{name} in @var{class}. The +returned method has one required argument, an instance of @var{class}, +and the specializer for that argument is @var{class}. When invoked, the +method returns the contents of the slot specified by @var{name} in the +instance; if the slot is uninitialized, an error of type +@code{condition-type:uninitialized-slot} is signalled. + +@lisp +@group +(define-generic get-bar (object)) + +(add-method get-bar + (slot-accessor-method 'bar)) +@end group +@end lisp @end deffn @deffn Procedure slot-modifier-method class name -Returns a modifier method for slot @var{name} in @var{class}. This -method has two required arguments, an instance of @var{class} and an -object. The specializer for the first argument is @code{class}; the -second argument is not specialized. When invoked, the method stores the -second argument in the slot specified by @var{name} in the instance. +Returns a modifier method for the slot @var{name} in @var{class}. The +returned method has two required arguments, an instance of @var{class} +and an object. The specializer for the first argument is @var{class} +and the second argument is not specialized. When invoked, the method +stores the second argument in the slot specified by @var{name} in the +instance. + +@lisp +@group +(define-generic set-bar! (object bar)) + +(add-method set-bar! + (slot-modifier-method 'bar)) +@end group +@end lisp @end deffn @deffn Procedure slot-initpred-method class name -Returns an ``initialized?''@: predicate method for slot @var{name} in -@var{class}. This method has one required argument, an instance of -@var{class}, and the specializer for that argument is @code{class}. -When invoked, the method returns @code{#t} if the slot specified by -@var{name} is initialized in the instance; otherwise it returns -@code{#f}. +Returns an ``initialized?''@: predicate method for the slot @var{name} +in @var{class}. The returned method has one required argument, an +instance of @var{class}, and the specializer for that argument is +@var{class}. When invoked, the method returns @code{#t} if the slot +specified by @var{name} is initialized in the instance; otherwise it +returns @code{#f}. + +@lisp +@group +(define-generic has-bar? (object)) + +(add-method has-bar? + (slot-initpred-method 'bar)) +@end group +@end lisp @end deffn -@deffn Procedure slot-value instance name -Returns the contents of the slot @var{name} in @var{instance}; -@var{name} may be either a symbol or a slot descriptor. If -@var{instance} does not have a slot of that name, or if the slot is not -initialized, an error is signalled. +@node Slot Access Constructors, Slot Access Procedures, Slot Access Methods, Slots +@subsection Slot Access Constructors + +For convenience, and for consistency with the record-accessor procedures +@code{record-accessor} and @code{record-modifier}, each of the above +method-generating procedures has a corresponding accessor-generator. +Each of these procedures creates a generic procedure, adds an +appropriate method to it by calling the corresponding method-generating +procedure, and returns the generic procedure. Thus, for example, the +following are equivalent: + +@lisp +@group +(slot-accessor 'bar) + +(let ((g (make-generic-procedure 1))) + (add-method g (slot-accessor-method 'bar)) + g) +@end group +@end lisp + +@deffn Procedure slot-accessor class name +Returns a generic procedure of one argument that is an accessor for the +slot @var{name} in @var{class}. The argument to the returned procedure +must be an instance of @var{class}. When the procedure is called, it +returns the contents of the slot @var{name} in that instance; if the +slot is uninitialized, an error of type +@code{condition-type:uninitialized-slot} is signalled. @end deffn -@deffn Procedure set-slot-value! instance name object -Modifies the slot @var{name} in @var{instance} to contain @var{object}; -@var{name} may be either a symbol or a slot descriptor. If -@var{instance} does not have a slot of that name, an error is signalled. +@deffn Procedure slot-modifier class name +Returns a generic procedure of two arguments that is a modifier for the +slot @var{name} in @var{class}. The first argument to the returned +procedure must be an instance of @var{class}, and the second argument +may be any object. When the procedure is called, it modifies the slot +@var{name} in the instance to contain the second argument. @end deffn -@deffn Procedure slot-initialized? instance name -Returns @code{#t} if the slot @var{name} in @var{instance} is -initialized, otherwise returns @code{#f}; @var{name} may be either a -symbol or a slot descriptor. If @var{instance} does not have a slot of -that name, an error is signalled. +@deffn Procedure slot-initpred class name +Returns a generic procedure of one argument that is an +``initialized?''@: predicate for the slot @var{name} in @var{class}. +The argument to the returned procedure must be an instance of +@var{class}. When the procedure is called, it returns @code{#t} if the +slot @var{name} in that instance is initialized, otherwise it returns +@code{#f}. @end deffn -A note on errors signalled by the slot-access mechanisms: in the MIT -Scheme implementation, these errors have specific condition types which -allow them to be caught and processed by condition handlers. The -condition signalled when an instance does not have a slot of the given -name has type @code{condition-type:unbound-slot}. The condition -signalled by an access to an uninitialized slot has type -@code{condition-type:uninitialized-instance-slot}. These condition -types are elements of the following condition type tree: +@node Slot Access Procedures, , Slot Access Constructors, Slots +@subsection Slot Access Procedures + +Finally, there is another set of three procedures, which access the +contents of a slot directly, given an instance and a slot name. These +procedures are very slow by comparison with the above. + +However, note the following. You can use these procedures in the body +of a @code{define-method} special form in an efficient way. If the +@code{define-method} specifies the correct number of arguments, the body +of the form contains a call to one of these procedures and nothing else, +and the specified slot name is quoted, the form is rewritten during +macro-expansion time as a call to the corresponding method-generating +procedure. For example, the following are equivalent: @lisp -condition-type:slot-error - condition-type:uninitialized-slot - condition-type:uninitialized-instance-slot - condition-type:unbound-slot +@group +(define-method p ((v )) + (slot-value v 'bar)) + +(add-method p + (slot-accessor-method 'bar)) +@end group @end lisp -@noindent -If you define a new kind of slot using the meta-object protocol, you -should create a sub-type of @code{condition-type:uninitialized-slot} to -signal access to uninitialized slots of that type. +@deffn Procedure slot-value instance name +Returns the contents of the slot @var{name} in @var{instance}; if the +slot is uninitialized, an error of type +@code{condition-type:uninitialized-slot} is signalled. +@end deffn -@node Generic Procedures, Methods, Slots, Language -@subsection Generic Procedures +@deffn Procedure set-slot-value! instance name object +Modifies the slot @var{name} in @var{instance} to contain @var{object}. +@end deffn +@deffn Procedure slot-initialized? instance name +Returns @code{#t} if the slot @var{name} in @var{instance} is +initialized, otherwise returns @code{#f}. +@end deffn + +@node Generic Procedures, Methods, Slots, Object System +@section Generic Procedures + +@cindex generic procedure Like an ordinary Scheme procedure, a generic procedure takes arguments, performs a series of operations, and perhaps returns useful values. An ordinary procedure has a single body of code that is always executed -when the procedure is called. A generic procedure has a set of bodies -of code of which a subset is selected for execution. The selected -bodies of code and the manner of their combination are determined by the -classes of one or more of the arguments to the generic procedure. +when the procedure is called. A generic procedure has a set of multiple +bodies of code, called methods, from which a subset is selected for +execution. The selected bodies of code and the manner of their +combination are determined by the classes of one or more of the +arguments to the generic procedure. Ordinary procedures and generic procedures are called with identical procedure-call syntax. @@ -805,43 +1164,69 @@ returned as values, and otherwise used in all the ways an ordinary procedure may be used. In particular, generic procedures satisfy the predicate @code{procedure?}. -@deffn Syntax define-generic-procedure name lambda-list -@deffnx Syntax define-generic-procedure name lambda-list body @dots{} -Defines @var{name} to be a generic procedure. In the first form, -@var{lambda-list} is an ordinary parameter list, which is exactly like -the parameter list in a @code{lambda} special form. This first form of -@code{define-generic-procedure} expands into +@menu +* Generic Procedure Datatype:: +* Method Storage:: +* Effective Method Procedure:: +@end menu + +@node Generic Procedure Datatype, Method Storage, Generic Procedures, Generic Procedures +@subsection Generic Procedure Datatype + +The following definitions are used to construct and inspect generic +procedures. + +@deffn Procedure make-generic-procedure arity [name] +Creates and returns a new generic procedure. The generic procedure +requires @var{arity} arguments. + +@var{Arity} may take one of the following forms. An exact positive +integer specifies that the procedure will accept exactly that number of +arguments. A pair of two exact positive integers specifies inclusive +lower and upper bounds, respectively, on the number of arguments +accepted; the @sc{cdr} may be @code{#f} indicating no upper bound. + +@var{Name} is used for debugging: it is a symbol that has no role in the +semantics of the generic procedure. @var{Name} may be @code{#f} to +indicate that the generic procedure is anonymous. If @var{name} is not +specified, it defaults to @code{#f}. + +Examples: @lisp +(define foo-bar (make-generic-procedure 2)) + +(define foo-baz (make-generic-procedure '(1 . 2) 'foo-baz)) + +(define foo-mum (make-generic-procedure '(1 . #f))) +@end lisp +@end deffn + +@deffn Syntax define-generic name lambda-list +Defines @var{name} to be a generic procedure. @var{Lambda-list} is an +ordinary parameter list, which is exactly like the parameter list in a +@code{lambda} special form. This expands into + +@lisp +@group (define @var{name} - (make-generic-procedure (quote @var{name}) - @var{min-arity} - @var{max-arity})) + (make-generic-procedure @var{arity} + (quote @var{name}))) +@end group @end lisp @noindent -where @var{min-arity} and @var{max-arity} are determined from -@var{lambda-list}. +where @var{arity} is determined from @var{lambda-list}. -The second form of @code{define-generic-procedure} has exactly the same -syntax as @code{define-method}, and expands into a sequence of the first -form of @code{define-generic-procedure} followed by a -@code{define-method}. -@end deffn +Examples (compare to examples of @code{make-generic-procedure}): -@deffn Procedure make-generic-procedure name min-arity max-arity -Creates and returns a new generic procedure. The generic procedure -requires at least @var{min-arity} arguments, and at most @var{max-arity} -arguments; if @var{max-arity} is @code{#f}, there is no upper bound on -the number of arguments accepted. +@lisp +(define-generic foo-bar (x y)) -@var{Name} is used for debugging: it is a symbol that has no role in the -semantics of the generic procedure. Alternatively, @var{name} may be -@code{#f} to indicate that the generic procedure is anonymous. +(define-generic foo-baz (x #!optional y)) -@var{Min-arity} must be an exact positive integer. @var{Max-arity} -must be @code{#f} or an exact integer greater than or equal to -@var{min-arity}. +(define-generic foo-mum (x . y)) +@end lisp @end deffn @deffn Procedure generic-procedure? object @@ -850,25 +1235,155 @@ returns @code{#f}. Note that every generic procedure satisfies the predicate @code{procedure?}. @end deffn -@node Methods, Record Classes, Generic Procedures, Language -@subsection Methods +@deffn Procedure generic-procedure-arity generic-procedure +Returns the arity of @var{generic-procedure}, as specified in the call +to @code{make-generic-procedure}. The returned arity must not be +modified. +@end deffn + +@deffn Procedure generic-procedure-name generic-procedure +Returns the name of @var{generic-procedure}, as specified in the call to +@code{make-generic-procedure}. +@end deffn + +@node Method Storage, Effective Method Procedure, Generic Procedure Datatype, Generic Procedures +@subsection Method Storage + +Methods are stored in generic procedures. When a generic procedure is +called, it selects a subset of its stored methods (using +@code{method-applicable?}), and arranges to invoke one or more of the +methods as necessary. The following definitions provide the means for +adding methods to and removing them from a generic procedure. + +@deffn Procedure add-method generic-procedure method +Adds @var{method} to @var{generic-procedure}. If +@var{generic-procedure} already has a method with the same specializers +as @var{method}, then the old method is discarded and @var{method} is +used in its place. +@end deffn + +@deffn Procedure delete-method generic-procedure method +Removes @var{method} from @var{generic-procedure}. Does nothing if +@var{generic-procedure} does not contain @var{method}. +@end deffn + +@deffn Procedure add-methods generic-procedure methods +Adds @var{methods}, which must be a list of methods, to +@var{generic-procedure}. Equivalent to calling @code{add-method} on +each method in @var{methods}. +@end deffn + +@deffn Procedure generic-procedure-methods generic-procedure +Returns a list of the methods contained in @var{generic-procedure}. The +returned list must not be modified. +@end deffn + +@node Effective Method Procedure, , Method Storage, Generic Procedures +@subsection Effective Method Procedure + +@cindex effective method procedure +@cindex emp +When a generic procedure is called, it arranges to invoke a subset of +its methods. This is done by @dfn{combining} the selected methods into +an @dfn{effective method procedure}, or @sc{emp}, then tail-recursively +invoking the @sc{emp}. @code{compute-effective-method-procedure} is the +procedure that is called to select the applicable methods and combine +them into an @sc{emp}. + +@deffn Procedure compute-effective-method-procedure generic-procedure classes +Collects the applicable methods of @var{generic-procedure} by calling +@code{method-applicable?} on each method and on @var{classes}. Combines +the resulting methods together into an effective method procedure, and +returns that @sc{emp}. +@end deffn + +@deffn Procedure compute-method generic-procedure classes +This procedure is like @code{compute-effective-method-procedure}, except +that it returns the result as a method whose specializers are +@var{classes}. + +@code{compute-method} is equivalent to + +@lisp +@group +(make-method @var{classes} + (compute-effective-method-procedure @var{generic-procedure} + @var{classes})) +@end group +@end lisp +@end deffn + +@node Methods, Printing, Generic Procedures, Object System +@section Methods + +@cindex method +A method contains a method procedure and a sequence of @dfn{parameter +specializers} that specify when the given method is applicable. + +A method is not a procedure and cannot be invoked as a procedure. +Methods are invoked by the effective method procedure when a generic +procedure is called. + +@menu +* Method Datatype:: +* Method Syntax:: +* Chained Methods:: +* Computed Methods:: +@end menu + +@node Method Datatype, Method Syntax, Methods, Methods +@subsection Method Datatype + +The following procedures are used to construct and inspect methods. + +@deffn Procedure make-method specializers procedure +Creates and returns a new method. Note that @var{specializers} may have +fewer elements than the number of required parameters in +@var{procedure}; the trailing parameters are considered to be +specialized by @code{}. + +After the returned method is stored in a generic procedure, +@var{Procedure} is called by the effective method procedure of the +generic procedure when the generic procedure is called with arguments +satisfying @var{specializers}. In simple cases, when no method +combination occurs, @var{procedure} @emph{is} the effective method +procedure. +@end deffn + +@deffn Procedure method? object +Returns @code{#t} iff @var{object} is a method, otherwise returns +@code{#f}. +@end deffn + +@deffn {Generic Procedure} method-specializers method +Returns the specializers of @var{method}. This list must not be +modified. +@end deffn + +@deffn {Generic Procedure} method-procedure method +Returns the procedure of @var{method}. +@end deffn -A method object contains a method procedure and a sequence of -@dfn{parameter specializers} that specify when the given method is -applicable. +@deffn Procedure method-applicable? method classes +This predicate is used to determine the applicability of @var{method}. +When a method is contained in a generic procedure, and the procedure is +applied to some arguments, the method is @dfn{applicable} if each +argument is an instance of the corresponding method specializer, or +equivalently, if each argument's class is a subclass of the +corresponding method specializer. + +@code{method-applicable?} determines whether @var{method} would be +applicable if the given arguments had the classes specified by +@var{classes}. It returns @code{#t} if each element of @var{classes} is +a subclass of the corresponding specializer of @var{method}, and +@code{#f} otherwise. +@end deffn -A method object is not a procedure and cannot be invoked as a procedure. -Various mechanisms in @sc{sos} take a method object and invoke its -method procedure, as is the case when a generic procedure is called. -When this occurs it is said that the method is invoked or called. +@node Method Syntax, Chained Methods, Method Datatype, Methods +@subsection Method Syntax -A leaf-method object is a special kind of method object that is faster -to invoke than a regular method object. It gains this speed by -sacrificing the ``call-next-method'' capability of regular methods (see -below). Note that the @code{define-method} and @code{method} special -forms will generate leaf-method objects automatically whenever the -method body does not contain a free reference to -@code{call-next-method}. +The following syntactic forms greatly simplify the definition of +methods, and of adding them to generic procedures. @deffn Syntax define-method generic-procedure lambda-list body @dots{} Defines a method of @var{generic-procedure}. @var{Lambda-list} is like @@ -884,10 +1399,12 @@ least one required parameter must be specialized. A @code{define-method} special form expands into the following: @lisp +@group (add-method @var{generic-procedure} (make-method (list @var{specializer} @dots{}) (lambda (call-next-method . @var{stripped-lambda-list}) @var{body} @dots{}))) +@end group @end lisp @noindent @@ -908,15 +1425,23 @@ For example, expands into @lisp +@group (add-method add (make-method (list ) (lambda (call-next-method x y) ...))) +@end group @end lisp Note that the list of specializers passed to @code{make-method} will correspond to the required parameters of the method; the specializer corresponding to a non-specialized required parameter is @code{}. + +Further note that, within the body of a @code{define-method} special +form, the free variable @code{call-next-method} is bound to a +``call-next-method'' procedure (see @code{make-chained-method} for +details). If the @code{define-method} body refers to this variable, the +defined method is a chained method, otherwise it is an ordinary method. @end deffn @deffn Syntax method lambda-list body @dots{} @@ -928,487 +1453,156 @@ are completely equivalent: @lisp @group -(define-method @var{generic-procedure} @var{lambda-list} - @var{body} @dots{}) +(define-method g ((a ) b) + (cons b a)) -(add-method @var{generic-procedure} - (method @var{lambda-list} - @var{body} @dots{})) -@end group -@end lisp -@end deffn - -@deffn Procedure add-method generic-procedure method -Adds @var{method} to @var{generic-procedure}. If -@var{generic-procedure} already has a method with the same specializers -as @var{method}, then the old method is discarded and @var{method} is -used in its place. -@end deffn +(add-method g + (method ((a ) b) + (cons b a))) -@deffn Procedure make-method specializers procedure -Creates and returns a new method object. @var{Specializers} must be a -non-null list of class objects. @var{Procedure} should accept one more -argument than the generic procedure to which this method will be added; -when called, the first argument will be a ``call-next-method'' -procedure, and the remaining arguments will be the arguments that were -passed to the generic procedure. The ``call-next-method'' procedure -accepts arguments, which are passed directly to the next method in place -of the generic procedure's arguments. It is the method writer's -responsibility to see that the ``call-next-method'' procedure's -arguments are sensible. - -@quotation -@strong{Please note:} In Dylan, calling the ``call-next-method'' -procedure with no arguments causes the next method to be called with the -arguments passed to the calling method; in @sc{sos}, this calls the next -method with no arguments. -@end quotation -@end deffn - -@deffn Procedure make-leaf-method specializers procedure -Creates and returns a new leaf method object. @var{Specializers} must -be a non-null list of class objects. @var{Procedure} should accept the -same number of arguments as the generic procedure to which this method -will be added; @var{procedure} will not be passed a ``call-next-method'' -procedure argument. -@end deffn - -@node Record Classes, , Methods, Language -@subsection Record Classes - -In the MIT Scheme implementation, @sc{sos} allows generic procedures to -discriminate on record types. This means that a record structure -defined by means of @code{make-record-type} or @code{define-structure} -can be passed as an argument to a generic procedure, and the generic -procedure can use the record's type to determine which method to be -invoked.@footnote{If the @code{type} option of @code{define-structure} -is used, the resulting data structure is @emph{not} a record and thus -cannot be used in this manner.} - -In order to support this, @sc{sos} has been extended to accept record -type descriptors as method specializers. Additionally, every record -type descriptor has an associated @sc{sos} class; either the class or -the record type can be used as a specializer with equivalent results. - -When a record type descriptor is created, an @sc{sos} class is -automatically created and associated with the descriptor. This class is -a direct subclass of @code{}, and is an instance of the -metaclass @code{}. The procedure @code{record-type-class} -can be used to obtain the class from the record type. - -@defvr Class -This is the metaclass of record classes. It is a direct subclass of -@code{}. -@end defvr - -@deffn Procedure record-type-class record-type -@var{Record-type} must be a record type descriptor (in other words, it -must satisfy the predicate @code{record-type?}). Returns the class -associated with @var{record-type}. -@end deffn - -@deffn Procedure record-class record -@var{Record} must be a record (in other words, it must satisfy the -predicate @code{record?}). Returns the class associated with -@var{record}. This is equivalent to - -@lisp -(record-type-class (record-type-descriptor @var{record})) +(add-method g + (make-method (list ) + (lambda (a b) + (cons b a)))) +@end group @end lisp @end deffn -@node Reflective Operations, Meta-Object Protocol, Language, Object System -@section Reflective Operations - -@menu -* Class Reflectives:: Reflective Operations on Classes -* Generic Reflectives:: Reflective Operations on Generic Procedures -* Method Reflectives:: Reflective Operations on Methods -* Slot Reflectives:: Reflective Operations on Slots -@end menu - -@node Class Reflectives, Generic Reflectives, , Reflective Operations -@subsection Reflective Operations on Classes - -@deffn Procedure class-name class -Returns the name of @var{class}. This is the @var{name} argument passed -to @code{make-class} when @var{class} was created. -@end deffn - -@deffn Procedure class-direct-superclasses class -Returns a list of the direct superclasses of @var{class}. If a -non-empty @var{direct-superclasses} argument was passed to -@code{make-class} when @var{class} was created, this list is -@code{equal?} to that argument. - -The returned value must not be modified. -@end deffn - -@deffn Procedure class-precedence-list class -Returns a list of the superclasses of @var{class}. The order of this -list is significant: it is the method resolution order. This list will -always have @var{class} as its first element, and @code{} as its -last element. - -The returned value must not be modified. -@end deffn - -@node Generic Reflectives, Method Reflectives, Class Reflectives, Reflective Operations -@subsection Reflective Operations on Generic Procedures - -Generic procedures have associated objects, called @dfn{generic -procedure instances}, that contain interesting information about the -generic procedure. The reflective operations for generic procedures do -not act directly on generic procedures, but rather on generic procedure -instances. This division might seem clumsy, but it serves a purpose: it -separates the accessing of reflective data in the instance from the -mapping between the generic procedure and its associated instance. This -is desirable because the mapping between a generic procedure and its -instance is much slower than an instance slot access. Specifically, -@code{procedure->generic} is a slow operation. - -@deffn Procedure procedure->generic procedure -If @var{procedure} is a generic procedure, this procedure returns the -generic procedure instance associated with @var{procedure}. Otherwise, -it returns @code{#f}. -@end deffn - -@deffn Procedure generic->procedure generic -Returns the generic procedure associated with @var{generic}. -@end deffn - -@deffn Procedure generic-name generic -@deffnx Procedure generic-min-arity generic -@deffnx Procedure generic-max-arity generic -These procedures return the arguments that were passed to -@code{make-generic-procedure} to create the generic procedure associated -with @var{generic}. -@end deffn - -@deffn Procedure generic-methods generic -Returns a list of the method objects that are contained in the generic -procedure associated with @var{generic}. This list is in no particular -order, and it must not be modified. -@end deffn - -@node Method Reflectives, Slot Reflectives, Generic Reflectives, Reflective Operations -@subsection Reflective Operations on Methods - -@deffn Procedure method-specializers method -Returns the list of specializers of @var{method}. This list must not be -modified. -@end deffn - -@deffn Procedure method-procedure method -Returns the procedure of @var{method}. If this is a regular method, the -returned procedure is the procedure that was passed to -@code{make-method} when @var{method} was constructed. If this is a leaf -method, the returned procedure is one that was specially constructed -when @code{make-leaf-method} was called. -@end deffn - -@deffn Procedure leaf-method-procedure leaf-method -Returns the procedure of @var{leaf-method}. This is the procedure that -was passed to @code{make-leaf-method} as an argument when -@var{leaf-method} was constructed. -@end deffn - -@node Slot Reflectives, , Method Reflectives, Reflective Operations -@subsection Reflective Operations on Slots - -@deffn Procedure slot-descriptors class -Returns a list of the slot descriptors for the slots of @var{class}. -This list is in no particular order and must not be modified. -@end deffn - -@deffn Procedure slot-descriptor class name -Returns the slot descriptor for the slot @var{name} in @var{class}. If -@var{class} has no slot of that name, an error is signalled. -@end deffn - -@deffn Procedure slot? object -Returns @code{#t} if @var{object} is a slot descriptor, otherwise -returns @code{#f}. -@end deffn - -@deffn Procedure slot-name slot -Returns the name of @var{slot}. -@end deffn - -@deffn Procedure slot-class slot -Returns the class of @var{slot}. This is the class with which -@var{slot} is associated. This is not necessarily the class that -defines @var{slot}; it could also be a subclass of that class. If the -slot was returned by @code{slot-descriptors} or @code{slot-descriptor}, -then this class is the argument passed to that procedure. -@end deffn - -@deffn Procedure slot-allocation slot -Returns the allocation of @var{slot}. This is a symbol that says how -the storage for the slot is allocated. For instance slots, this symbol -is @code{instance}. -@end deffn - -@deffn Procedure slot-initializer slot -Returns the initializer for @var{slot}. This is a procedure of no -arguments that is called to produce an initial value for @var{slot}. -The initializer may also be @code{#f} meaning that the slot has no -initializer. +@node Chained Methods, Computed Methods, Method Syntax, Methods +@subsection Chained Methods + +@cindex chained method +Sometimes it is useful to have a method that adds functionality to +existing methods. @dfn{Chained methods} provide a mechanism to +accomplish this. A chained method, when invoked, can call the method +that would have been called had this method not been defined: it is +passed a procedure that will call the inherited method. The chained +method can run arbitrary code both before and after calling the +inherited method. + +@deffn Procedure make-chained-method specializers procedure +Create and return a chained method. @var{Procedure} must be a procedure +of one argument that returns a procedure. When the chained method is +combined, its procedure will be called with one argument, a +``call-next-method'' procedure; it must then return another procedure +that will be called when the method is invoked. The +``call-next-method'' procedure may called by the method procedure at any +time, which will invoke the next less-specific method. The +``call-next-method'' procedure must be called with the same number of +arguments as the method procedure; normally these are the same +arguments, but that is not required. @end deffn -@deffn Procedure slot-plist slot -Returns the property list of @var{slot}. This list is constructed from -the class definitions that contributed to @var{slot}'s definition. This -list must not be modified. +@deffn Procedure chained-method? object +Returns @code{#t} if @var{object} is a chained method, otherwise returns +@code{#f}. Note that every chained method satisfies @code{method?}. @end deffn -@deffn Procedure slot-plist-lookup plist name default -Looks up @var{name} in @var{plist}. If found, the associated datum is -returned; otherwise, @var{default} is returned. @var{Default} may be -any object. -@end deffn - -@deffn Procedure slot-property slot name [default] -Looks up @var{name} in @var{slot}'s property list. If found, the -associated datum is returned. Otherwise, if @var{default} is given it -is returned. Otherwise, an error is signalled. @var{Default}, if -given, may be any object. -@end deffn - -@node Meta-Object Protocol, Miscellany, Reflective Operations, Object System -@section The Meta-Object Protocol - -@menu -* Generic Invocation Subprotocol:: -* Instantiation Subprotocol:: -* Class Initialization Subprotocol:: -@end menu - -@node Generic Invocation Subprotocol, Instantiation Subprotocol, , Meta-Object Protocol -@subsection The Generic Invocation Subprotocol - -@deffn {Generic Procedure} compute-apply-generic generic -@cindex discriminating procedure -Computes and returns the @dfn{discriminating procedure} for -@var{generic}. - -This generic procedure is called to determine the discriminating -procedure for a generic procedure. When a generic procedure is called, -the @emph{installed} discriminating procedure is called with the full -set of arguments received by the generic procedure, and must implement -the behavior of calling the generic procedure: determining the ordered -set of applicable methods, determining the effective method procedure, -and running the effective method procedure. - -To determine the ordered set of applicable methods, the discriminating -procedure calls @code{compute-methods}. The discriminating procedure is -permitted to memoize the value of @code{compute-methods} as follows. -The discriminating procedure may reuse the list of applicable methods -without calling @code{compute-methods} again provided that all of the -following are true: - -@enumerate +@node Computed Methods, , Chained Methods, Methods +@subsection Computed Methods + +@cindex computed method +A @dfn{computed method} is a powerful mechanism that provides the +ability to generate methods ``on the fly''. A computed method is like +an ordinary method, except that its procedure is called during method +combination, and is passed the classes of the arguments in place of the +arguments themselves. Based on these classes, the computed method +returns an ordinary method, which is combined in the usual way. + +Note that computed methods and computed @sc{emp}s both satisfy the +predicate @code{method?}. They are not really methods in that they +cannot be combined with other methods to form an effective method +procedure; however, they are treated as methods by procedures such as +@code{add-method} and @code{method-specializers}. + +@deffn Procedure make-computed-method specializers procedure +Create and return a computed method. @var{Procedure} will be called +during method combination with the classes of the generic-procedure +arguments as its arguments. It must return one of the following: + +@itemize @bullet @item -The generic procedure is being called again with required arguments -which are instances of the same classes. +An ordinary method (as returned by @code{make-method} or +@code{make-chained-method}). The returned method's specializers must be +restrictions of @var{specializers}, i.e.@: each specializer in the +returned method must be a subclass of the corresponding specializer in +@var{specializers}. In the usual case, the returned method's +specializers are the same as @var{specializers}. @item -The generic procedure has not been reinitialized. +A procedure, which is converted into an ordinary method by calling +@code{make-method} on @var{specializers} and the returned procedure. @item -No method has been added to or removed from the generic procedure. - -@item -For all of the specializers of all the generic procedure's methods which -are classes, their class precedence lists have not changed. - -@item -For any such memoized value, the class precedence list of the class of -each of the required arguments has not changed. -@end enumerate - -Determination of the effective method procedure is done by calling -@code{compute-effective-method-procedure}. When the effective method -procedure is run, the first applicable method's procedure is called. -The first argument to that procedure is a ``call-next-method'' -procedure, and the remaining arguments are the arguments that were -received by the generic procedure. If the first argument calls the -``call-next-method'' procedure, then the next method in the sequence of -applicable methods is invoked. The arguments to the next method's -procedure are a ``call-next-method'' procedure, followed by the -arguments received by the first method's ``call-next-method'' procedure. -This process continues until there are no more applicable methods or -until one of the methods does not call its ``call-next-method'' -procedure. - -The generic procedure @code{compute-apply-generic} is called, and its -result installed, by @code{add-method}. - -This procedure is similar to @code{compute-discriminating-function} in -@sc{clos}. +@code{#f}, which means that the computed method declines to generate a +method. +@end itemize @end deffn -@deffn {Generic Procedure} compute-methods generic classes -@var{Classes} is a non-empty list of class objects. This generic -procedure returns a list of method objects. - -This generic procedure is called to determine the method applicability -of a generic procedure given only the classes of the required arguments. -This generic procedure returns that list as its value. The returned list -of method objects is sorted by precedence order, the most specific -method coming first. If no methods are applicable to arguments with the -specified classes, the empty list is returned. - -The result of the generic procedure @code{compute-method-more-specific?} -is used to sort the returned list of methods. - -When a generic procedure is invoked, the discriminating procedure must -determine the ordered list of methods applicable to its arguments. -Depending on the generic procedure and its arguments, this is done in -one of two ways: using a memoized value; or calling -@code{compute-methods}. (Refer to the description of -@code{compute-apply-generic} for the details of this process.) - -The list returned by this generic procedure will not be mutated by the -implementation. The results are undefined if a program mutates the list -returned by this generic procedure. - -The primary method of this generic procedure is specialized on -@code{}. This method can be overridden. - -@quotation -Remarks: This generic procedure exists to allow user extensions which -alter method lookup rules, but which base the new rules only on the -classes of the required arguments, to take advantage of the class-based -method lookup memoization in the implementation. - -To get appropriate performance, other kinds of extensions may require -methods on @code{compute-apply-generic} which implement their own -memoization scheme. -@end quotation - -This procedure is similar to -@code{compute-applicable-methods-using-classes} in @sc{clos}. -@end deffn - -@deffn {Generic Procedure} compute-method-more-specific? generic -This generic procedure computes and returns a procedure of three -arguments. - -This generic procedure is called to determine a sorting predicate which -can be used by @code{compute-methods} to order a set of methods. The -sorting predicate is a procedure of three arguments; the first two -arguments are the methods being compared, and the third argument is a -list of the classes of the required arguments to the generic procedure -whose methods are being sorted. The result of the sorting predicate is -a true value if the first method is more specific than the second method -(given the required argument classes of the third argument); otherwise, -the result is @code{#f}. - -The arguments passed to the sorting predicate must not be modified. - -This generic procedure is called by @code{compute-methods}. -@end deffn - -@deffn {Generic Procedure} compute-effective-method-procedure generic methods -@cindex effective method procedure -@var{Methods} must be a list of method objects. - -This generic procedure is called to determine the effective method -procedure from a sorted list of method objects. - -An effective method procedure is a procedure that describes how the -applicable methods are to be combined. It is invoked with the arguments -passed to the generic procedure associated with @var{generic}, and -invokes the first applicable method with those arguments, preceded by a -``call-next-method'' argument, as described earlier for -@code{compute-apply-generic}. - -This generic procedure can be called by the user or the implementation. -It is called by discriminating procedures whenever a sorted list of -applicable methods must be converted to an effective method procedure. - -The primary method of this generic procedure is specialized on -@code{}. This method can be overwritten. - -This procedure is similar to @code{compute-effective-method} in -@sc{clos}. -@end deffn - -@node Instantiation Subprotocol, Class Initialization Subprotocol, Generic Invocation Subprotocol, Meta-Object Protocol -@subsection The Instantiation Subprotocol - -@deffn {Generic Procedure} allocate-instance class -Called by @code{make-instance} to allocate a new instance; should not be -called by applications. -@end deffn - -@deffn {Generic Procedure} initialize-instance instance initarg @dots{} -Called by @code{make-instance} to initialize a newly allocated instance; -should not be called by applications. @var{initarg}s are the -@var{initarg}s arguments that were passed to @code{make-instance}. The -default method for this procedure accepts no @var{initarg}s; if you wish -to pass arguments to @code{make-instance} you must define a -corresponding method on @code{initialize-instance} to decipher the -meaning of those arguments. +@deffn Procedure computed-method? object +Returns @code{#t} if @var{object} is a computed method, otherwise +returns @code{#f}. @end deffn -@node Class Initialization Subprotocol, , Instantiation Subprotocol, Meta-Object Protocol -@subsection The Class Initialization Subprotocol - -@deffn {Generic Procedure} compute-precedence-list class -@end deffn +@cindex computed emps +A @dfn{computed @sc{emp}} takes the computed-method mechanism one step +further. A computed @sc{emp} is like a computed method, except that it +returns an effective method procedure rather than a method. +@code{compute-effective-method-procedure} tries each of the applicable +computed @sc{emp}s, and if exactly one of them returns an @sc{emp}, that +is the resulting effective method procedure. + +@deffn Procedure make-computed-emp key specializers procedure +Create and return a computed @sc{emp}. @var{Procedure} will be called +during method combination with the classes of the generic-procedure +arguments as its arguments. It must return either an @sc{emp} or +@code{#f}. -@deffn {Generic Procedure} compute-slots class +@var{Key} is an arbitrary object that is used to identify the computed +@sc{emp}. The @var{key} is used by @code{add-method} and +@code{delete-method} to decide whether two computed @sc{emp}s are +the same; they are the same if their @var{key}s are @code{equal?}. This +is necessary because a generic procedure may have more than one computed +@sc{emp} with the same specializers. @end deffn -@deffn {Generic Procedure} compute-slot-descriptor class slots +@deffn Procedure computed-emp? object +Returns @code{#t} if @var{object} is a computed @sc{emp}, otherwise +returns @code{#f}. @end deffn -@deffn Procedure make-slot name class allocation initializer plist -Creates and returns a new slot descriptor. @var{Allocation} must be a -symbol. @var{Initializer} must be @code{#f} or a procedure of no -arguments. This should be called only by methods of -@code{compute-slot-descriptor}. +@deffn {Generic Procedure} computed-emp-key computed-emp +Returns the key for @var{computed-emp}. @end deffn -@deffn {Generic Procedure} compute-virtual-slot-accessors class slot -@end deffn +@node Printing, , Methods, Object System +@section Printing -@node Miscellany, , Meta-Object Protocol, Object System -@section Miscellany +@cindex printing instances +The following procedures can be used to define a custom printed +representation for an instance. It is highly recommended that instances +be printed by @code{write-instance-helper}, as this ensures a uniform +appearance for all objects. -@deffn {Generic Procedure} write-instance instance output-port -This is called by the default method on @code{unparse-instance} to -generate the printed representation of @var{instance}. Users should -define methods on this procedure in preference to -@code{unparse-instance} since the former is not portable. +@deffn {Generic Procedure} write-instance instance port +This is called by the runtime system to generate the printed +representation of @var{instance}. The methods of this procedure should +write the representation to @var{port}. @end deffn -@deffn {Generic Procedure} unparse-instance instance state -This is called automatically by the unparser when it tries to print an -instance; it should not be called by applications. @var{Instance} is -the instance to be printed, and @var{state} is an unparser-state object. - -This generic procedure is only defined in the MIT Scheme implementation. -@end deffn +@deffn Procedure write-instance-helper name instance port thunk +This writes a standardized ``frame'' for a printed representation +method. It generates the following output on @var{port}: -@deffn Procedure ppi object -``Pretty print'' @var{object}. If @var{object} is an instance, the -slots of the instance are individually pretty printed. Otherwise, the -procedure @code{pp} is called with @var{object} as its argument. +@lisp +#[@var{name} @var{hash-number}@dots{}] +@end lisp -This procedure is a kludge that would not be needed if the pretty -printer had some kind of hook which would enable this behavior to be -specified. +@noindent +where @var{hash-number} is the result of calling @code{hash} on +@var{instance}, and @dots{} is the output generated by @var{thunk}. @end deffn -@defvr Class -@end defvr - -@defvr Class -@end defvr - @node Variable Index, Concept Index, Object System, Top @unnumbered Variable Index @printindex fn -- 2.25.1