diff --git a/doc/goops/.cvsignore b/doc/goops/.cvsignore new file mode 100644 index 000000000..896c69f47 --- /dev/null +++ b/doc/goops/.cvsignore @@ -0,0 +1,22 @@ +Makefile +Makefile.in +stamp-vti +stamp-vti.1 +*.log +*.dvi +*.aux +*.toc +*.cp +*.fn +*.vr +*.tp +*.ky +*.pg +*.cps +*.fns +*.tps +*.vrs +*.ps +*.info* +*.html +goops.tmp diff --git a/doc/goops/Makefile.am b/doc/goops/Makefile.am new file mode 100644 index 000000000..8a2661dfd --- /dev/null +++ b/doc/goops/Makefile.am @@ -0,0 +1,39 @@ +## Process this file with Automake to create Makefile.in +## +## Copyright (C) 1998 Free Software Foundation, Inc. +## +## This file is part of GUILE. +## +## GUILE is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as +## published by the Free Software Foundation; either version 2, or +## (at your option) any later version. +## +## GUILE is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public +## License along with GUILE; see the file COPYING. If not, write +## to the Free Software Foundation, Inc., 59 Temple Place, Suite +## 330, Boston, MA 02111-1307 USA + +AUTOMAKE_OPTIONS = gnu + +info_TEXINFOS = goops.texi + +goops_TEXINFOS = goops-tutorial.texi hierarchy.eps hierarchy.txt ../AUTHORS + +# Optionally support building an HTML version of the manual. + +if HTMLDOC + +htmldir = $(prefix)/html/guile-$(VERSION) + +html_DATA = goops_toc.html $(shell ls goops_*.html 2>/dev/null) + +goops_toc.html: goops.texi $(goops_TEXINFOS) + $(TEXI2HTML) -split_chapter goops.texi + +endif diff --git a/doc/goops/goops-tutorial.texi b/doc/goops/goops-tutorial.texi new file mode 100644 index 000000000..7ab6ebcf0 --- /dev/null +++ b/doc/goops/goops-tutorial.texi @@ -0,0 +1,810 @@ +@c Original attribution: + +@c +@c STk Reference manual (Appendix: An Introduction to STklos) +@c +@c Copyright © 1993-1999 Erick Gallesio - I3S-CNRS/ESSI +@c Permission to use, copy, modify, distribute,and license this +@c software and its documentation for any purpose is hereby granted, +@c provided that existing copyright notices are retained in all +@c copies and that this notice is included verbatim in any +@c distributions. No written agreement, license, or royalty fee is +@c required for any of the authorized uses. +@c This software is provided ``AS IS'' without express or implied +@c warranty. +@c + +@c Adapted for use in Guile with the authors permission + +@c @macro goops @c was {\stklos} +@c GOOPS +@c @end macro + +@c @macro guile @c was {\stk} +@c Guile +@c @end macro + +This is chapter was originally written by Erick Gallesio as an appendix +for the STk reference manual, and subsequently adapted to @goops{}. + +@menu +* Copyright:: +* Intro:: +* Class definition and instantiation:: +* Inheritance:: +* Generic functions:: +@end menu + +@node Copyright, Intro, Tutorial, Tutorial +@section Copyright + +Original attribution: + +STk Reference manual (Appendix: An Introduction to STklos) + +Copyright © 1993-1999 Erick Gallesio - I3S-CNRS/ESSI +Permission to use, copy, modify, distribute,and license this +software and its documentation for any purpose is hereby granted, +provided that existing copyright notices are retained in all +copies and that this notice is included verbatim in any +distributions. No written agreement, license, or royalty fee is +required for any of the authorized uses. +This software is provided ``AS IS'' without express or implied +warranty. + +Adapted for use in Guile with the authors permission + +@node Intro, Class definition and instantiation, Copyright, Tutorial +@section Introduction + +@goops{} is the object oriented extension to @guile{}. Its +implementation is derived from @w{STk-3.99.3} by Erick Gallesio and +version 1.3 of the Gregor Kiczales @cite{Tiny-Clos}. It is very close +to CLOS, the Common Lisp Object System (@cite{CLtL2}) but is adapted for +the Scheme language. + +Briefly stated, the @goops{} extension gives the user a full object +oriented system with multiple inheritance and generic functions with +multi-method dispatch. Furthermore, the implementation relies on a true +meta object protocol, in the spirit of the one defined for CLOS +(@cite{Gregor Kiczales: A Metaobject Protocol}). + +The purpose of this tutorial is to introduce briefly the @goops{} +package and in no case will it replace the @goops{} reference manual +(which needs to be urgently written now@ @dots{}). + +Note that the operations described in this tutorial resides in modules +that may need to be imported before being available. The main module is +imported by evaluating: + +@lisp +(use-modules (oop goops)) +@end lisp +@findex (oop goops) +@cindex main module +@cindex loading +@cindex preparing + +@node Class definition and instantiation, Inheritance, Intro, Tutorial +@section Class definition and instantiation + +@menu +* Class definition:: +@end menu + +@node Class definition, , Class definition and instantiation, Class definition and instantiation +@subsection Class definition + +A new class is defined with the @code{define-class}@footnote{Don't +forget to import the @code{(oop goops)} module} macro. The syntax of +@code{define-class} is close to CLOS @code{defclass}: + +@findex define-class +@cindex class +@lisp +(define-class @var{class} (@var{superclass} @dots{}) + @var{slot-description} @dots{} + @var{class-option} @dots{}) +@end lisp + +Class options will not be discussed in this tutorial. The list of +@var{superclass}es specifies which classes to inherit properties from +@var{class} (see @ref{Inheritance} for more details). A +@var{slot-description} gives the name of a slot and, eventually, some +``properties'' of this slot (such as its initial value, the function +which permit to access its value, @dots{}). Slot descriptions will be +discussed in @ref{Slot description}. +@cindex slot + +As an example, let us define a type for representation of complex +numbers in terms of real numbers. This can be done with the following +class definition: + +@lisp +(define-class () + r i) +@end lisp + +This binds the variable @code{}@footnote{@code{} is in +fact a builtin class in GOOPS. Because of this, GOOPS will create a new +class. The old class will still serve as the type for Guile's native +complex numbers.} to a new class whose instances contain two +slots. These slots are called @code{r} an @code{i} and we suppose here +that they contain respectively the real part and the imaginary part of a +complex number. Note that this class inherits from @code{} which +is a pre-defined class. (@code{} is the direct super class of +the pre-defined class @code{} which, in turn, is the super +class of @code{} which is the super of +@code{}.)@footnote{With the new definition of @code{}, +a @code{} is not a @code{} since @code{} inherits +from @code{ } rather than @code{}. In practice, +inheritance could be modified @emph{a posteriori}, if needed. However, +this necessitates some knowledge of the meta object protocol and it will +not be shown in this document}. + +@node Inheritance, Generic functions, Class definition and instantiation, Tutorial +@section Inheritance +@c \label{inheritance} + +@menu +* Class hierarchy and inheritance of slots:: +* Instance creation and slot access:: +* Slot description:: +* Class precedence list:: +@end menu + +@node Class hierarchy and inheritance of slots, Instance creation and slot access, Inheritance, Inheritance +@subsection Class hierarchy and inheritance of slots +Inheritance is specified upon class definition. As said in the +introduction, @goops{} supports multiple inheritance. Here are some +class definitions: + +@lisp +(define-class A () a) +(define-class B () b) +(define-class C () c) +(define-class D (A B) d a) +(define-class E (A C) e c) +(define-class F (D E) f) +@end lisp + +@code{A}, @code{B}, @code{C} have a null list of super classes. In this +case, the system will replace it by the list which only contains +@code{}, the root of all the classes defined by +@code{define-class}. @code{D}, @code{E}, @code{F} use multiple +inheritance: each class inherits from two previously defined classes. +Those class definitions define a hierarchy which is shown in Figure@ 1. +In this figure, the class @code{} is also shown; this class is the +super class of all Scheme objects. In particular, @code{} is the +super class of all standard Scheme types. + +@example +@group +@image{hierarchy} +@center @emph{Fig 1: A class hierarchy} +@iftex +@emph{(@code{} which is the direct subclass of @code{} +and the direct superclass of @code{} has been omitted in this +figure.)} +@end iftex +@end group +@end example + +The set of slots of a given class is calculated by taking the union of the +slots of all its super class. For instance, each instance of the class +D, defined before will have three slots (@code{a}, @code{b} and +@code{d}). The slots of a class can be obtained by the @code{class-slots} +primitive. For instance, + +@lisp +(class-slots A) @result{} ((a)) +(class-slots E) @result{} ((a) (e) (c)) +(class-slots F) @result{} ((e) (c) (b) (d) (a) (f)) +@c used to be ((d) (a) (b) (c) (f)) +@end lisp + +@emph{Note: } The order of slots is not significant. + +@node Instance creation and slot access, Slot description, Class hierarchy and inheritance of slots, Inheritance +@subsection Instance creation and slot access + +Creation of an instance of a previously defined +class can be done with the @code{make} procedure. This +procedure takes one mandatory parameter which is the class of the +instance which must be created and a list of optional +arguments. Optional arguments are generally used to initialize some +slots of the newly created instance. For instance, the following form + +@findex make +@cindex instance +@lisp +(define c (make )) +@end lisp + +will create a new @code{} object and will bind it to the @code{c} +Scheme variable. + +Accessing the slots of the new complex number can be done with the +@code{slot-ref} and the @code{slot-set!} primitives. @code{Slot-set!} +primitive permits to set the value of an object slot and @code{slot-ref} +permits to get its value. + +@findex slot-set! +@findex slot-ref +@lisp +@group +(slot-set! c 'r 10) +(slot-set! c 'i 3) +(slot-ref c 'r) @result{} 10 +(slot-ref c 'i) @result{} 3 +@end group +@end lisp + +Using the @code{describe} function is a simple way to see all the +slots of an object at one time: this function prints all the slots of an +object on the standard output. + +First load the module @code{(oop goops describe)}: + +@example +@code{(use-modules (oop goops describe))} +@end example + +The expression + +@smalllisp +(describe c) +@end smalllisp + +will now print the following information on the standard output: + +@lisp +#< 401d8638> is an instance of class +Slots are: + r = 10 + i = 3 +@end lisp + +@node Slot description, Class precedence list, Instance creation and slot access, Inheritance +@subsection Slot description +@c \label{slot-description} + +When specifying a slot, a set of options can be given to the +system. Each option is specified with a keyword. The list of authorized +keywords is given below: + +@cindex keyword +@itemize @bullet +@item +@code{#:init-value} permits to supply a default value for the slot. This +default value is obtained by evaluating the form given after the +@code{#:init-form} in the global environment, at class definition time. +@cindex default slot value +@findex #:init-value +@cindex top level environment + +@item +@code{#:init-thunk} permits to supply a thunk that will provide a +default value for the slot. The value is obtained by evaluating the +thunk a instance creation time. +@c CHECKME: in the global environment? +@findex default slot value +@findex #:init-thunk +@cindex top level environment + +@item +@code{#:init-keyword} permits to specify the keyword for initializing a +slot. The init-keyword may be provided during instance creation (i.e. in +the @code{make} optional parameter list). Specifying such a keyword +during instance initialization will supersede the default slot +initialization possibly given with @code{#:init-form}. +@findex #:init-keyword + +@item +@code{#:getter} permits to supply the name for the +slot getter. The name binding is done in the +environment of the @code{define-class} macro. +@findex #:getter +@cindex top level environment +@cindex getter + +@item +@code{#:setter} permits to supply the name for the +slot setter. The name binding is done in the +environment of the @code{define-class} macro. +@findex #:setter +@cindex top level environment +@cindex setter + +@item +@code{#:accessor} permits to supply the name for the +slot accessor. The name binding is done in the global +environment. An accessor permits to get and +set the value of a slot. Setting the value of a slot is done with the extended +version of @code{set!}. +@findex set! +@findex #:accessor +@cindex top level environment +@cindex accessor + +@item +@code{#:allocation} permits to specify how storage for +the slot is allocated. Three kinds of allocation are provided. +They are described below: + +@itemize @minus +@item +@code{#:instance} indicates that each instance gets its own storage for +the slot. This is the default. +@item +@code{#:class} indicates that there is one storage location used by all +the direct and indirect instances of the class. This permits to define a +kind of global variable which can be accessed only by (in)direct +instances of the class which defines this slot. +@item +@code{#:each-subclass} indicates that there is one storage location used +by all the direct instances of the class. In other words, if two classes +are not siblings in the class hierarchy, they will not see the same +value. +@item +@code{#:virtual} indicates that no storage will be allocated for this +slot. It is up to the user to define a getter and a setter function for +this slot. Those functions must be defined with the @code{#:slot-ref} +and @code{#:slot-set!} options. See the example below. +@findex #:slot-set! +@findex #:slot-ref +@findex #:virtual +@findex #:class +@findex #:each-subclass +@findex #:instance +@findex #:allocation +@end itemize +@end itemize + +To illustrate slot description, we shall redefine the @code{} class +seen before. A definition could be: + +@lisp +(define-class () + (r #:init-value 0 #:getter get-r #:setter set-r! #:init-keyword #:r) + (i #:init-value 0 #:getter get-i #:setter set-i! #:init-keyword #:i)) +@end lisp + +With this definition, the @code{r} and @code{i} slot are set to 0 by +default. Value of a slot can also be specified by calling @code{make} +with the @code{#:r} and @code{#:i} keywords. Furthermore, the generic +functions @code{get-r} and @code{set-r!} (resp. @code{get-i} and +@code{set-i!}) are automatically defined by the system to read and write +the @code{r} (resp. @code{i}) slot. + +@lisp +(define c1 (make #:r 1 #:i 2)) +(get-r c1) @result{} 1 +(set-r! c1 12) +(get-r c1) @result{} 12 +(define c2 (make #:r 2)) +(get-r c2) @result{} 2 +(get-i c2) @result{} 0 +@end lisp + +Accessors provide an uniform access for reading and writing an object +slot. Writing a slot is done with an extended form of @code{set!} +which is close to the Common Lisp @code{setf} macro. So, another +definition of the previous @code{} class, using the +@code{#:accessor} option, could be: + +@findex set! +@lisp +(define-class () + (r #:init-value 0 #:accessor real-part #:init-keyword #:r) + (i #:init-value 0 #:accessor imag-part #:init-keyword #:i)) +@end lisp + +Using this class definition, reading the real part of the @code{c} +complex can be done with: +@lisp +(real-part c) +@end lisp +and setting it to the value contained in the @code{new-value} variable +can be done using the extended form of @code{set!}. +@lisp +(set! (real-part c) new-value) +@end lisp + +Suppose now that we have to manipulate complex numbers with rectangular +coordinates as well as with polar coordinates. One solution could be to +have a definition of complex numbers which uses one particular +representation and some conversion functions to pass from one +representation to the other. A better solution uses virtual slots. A +complete definition of the @code{} class using virtual slots is +given in Figure@ 2. + +@example +@group +@lisp +(define-class () + ;; True slots use rectangular coordinates + (r #:init-value 0 #:accessor real-part #:init-keyword #:r) + (i #:init-value 0 #:accessor imag-part #:init-keyword #:i) + ;; Virtual slots access do the conversion + (m #:accessor magnitude #:init-keyword #:magn + #:allocation #:virtual + #:slot-ref (lambda (o) + (let ((r (slot-ref o 'r)) (i (slot-ref o 'i))) + (sqrt (+ (* r r) (* i i))))) + #:slot-set! (lambda (o m) + (let ((a (slot-ref o 'a))) + (slot-set! o 'r (* m (cos a))) + (slot-set! o 'i (* m (sin a)))))) + (a #:accessor angle #:init-keyword #:angle + #:allocation #:virtual + #:slot-ref (lambda (o) + (atan (slot-ref o 'i) (slot-ref o 'r))) + #:slot-set! (lambda(o a) + (let ((m (slot-ref o 'm))) + (slot-set! o 'r (* m (cos a))) + (slot-set! o 'i (* m (sin a))))))) + +@end lisp +@center @emph{Fig 2: A @code{} number class definition using virtual slots} +@end group +@end example + +@sp 3 +This class definition implements two real slots (@code{r} and +@code{i}). Values of the @code{m} and @code{a} virtual slots are +calculated from real slot values. Reading a virtual slot leads to the +application of the function defined in the @code{#:slot-ref} +option. Writing such a slot leads to the application of the function +defined in the @code{#:slot-set!} option. For instance, the following +expression + +@findex #:slot-set! +@findex #:slot-ref +@lisp +(slot-set! c 'a 3) +@end lisp + +permits to set the angle of the @code{c} complex number. This expression +conducts, in fact, to the evaluation of the following expression + +@lisp +((lambda o m) + (let ((m (slot-ref o 'm))) + (slot-set! o 'r (* m (cos a))) + (slot-set! o 'i (* m (sin a)))) + c 3) +@end lisp + +A more complete example is given below: + +@example +@group +@lisp +(define c (make #:r 12 #:i 20)) +(real-part c) @result{} 12 +(angle c) @result{} 1.03037682652431 +(slot-set! c 'i 10) +(set! (real-part c) 1) +(describe c) @result{} + #< 401e9b58> is an instance of class + Slots are: + r = 1 + i = 10 + m = 10.0498756211209 + a = 1.47112767430373 +@end lisp +@end group +@end example + +Since initialization keywords have been defined for the four slots, we +can now define the @code{make-rectangular} and @code{make-polar} standard +Scheme primitives. + +@lisp +(define make-rectangular + (lambda (x y) (make #:r x #:i y))) + +(define make-polar + (lambda (x y) (make #:magn x #:angle y))) +@end lisp + +@node Class precedence list, , Slot description, Inheritance +@subsection Class precedence list + +A class may have more than one superclass. @footnote{This section is an +adaptation of Jeff Dalton's (J.Dalton@@ed.ac.uk) @cite{Brief +introduction to CLOS}} With single inheritance (one superclass), it is +easy to order the super classes from most to least specific. This is the +rule: + +@display +@cartouche +Rule 1: Each class is more specific than its superclasses.@c was \bf +@end cartouche +@end display + +With multiple inheritance, ordering is harder. Suppose we have + +@lisp +(define-class X () + (x #:init-value 1)) + +(define-class Y () + (x #:init-value 2)) + +(define-class Z (X Y) + (@dots{})) +@end lisp + +In this case, the @code{Z} class is more specific than the @code{X} or +@code{Y} class for instances of @code{Z}. However, the @code{#:init-value} +specified in @code{X} and @code{Y} leads to a problem: which one +overrides the other? The rule in @goops{}, as in CLOS, is that the +superclasses listed earlier are more specific than those listed later. +So: + +@display +@cartouche +Rule 2: For a given class, superclasses listed earlier are more + specific than those listed later. +@end cartouche +@end display + +These rules are used to compute a linear order for a class and all its +superclasses, from most specific to least specific. This order is +called the ``class precedence list'' of the class. Given these two +rules, we can claim that the initial form for the @code{x} slot of +previous example is 1 since the class @code{X} is placed before @code{Y} +in class precedence list of @code{Z}. + +These two rules are not always enough to determine a unique order, +however, but they give an idea of how things work. Taking the @code{F} +class shown in Figure@ 1, the class precedence list is + +@example +(f d e a c b ) +@end example + +However, it is usually considered a bad idea for programmers to rely on +exactly what the order is. If the order for some superclasses is important, +it can be expressed directly in the class definition. + +The precedence list of a class can be obtained by the function +@code{class-precedence-list}. This function returns a ordered +list whose first element is the most specific class. For instance, + +@lisp +(class-precedence-list B) @result{} (#< B 401b97c8> + #< 401e4a10> + #< 4026a9d8>) +@end lisp + +However, this result is not too much readable; using the function +@code{class-name} yields a clearer result: + +@lisp +(map class-name (class-precedence-list B)) @result{} (B ) +@end lisp + +@node Generic functions, , Inheritance, Tutorial +@section Generic functions + +@menu +* Generic functions and methods:: +* Next-method:: +* Example:: +@end menu + +@node Generic functions and methods, Next-method, Generic functions, Generic functions +@subsection Generic functions and methods + +@c \label{gf-n-methods} +Neither @goops{} nor CLOS use the message mechanism for methods as most +Object Oriented language do. Instead, they use the notion of +@dfn{generic functions}. A generic function can be seen as a methods +``tanker''. When the evaluator requested the application of a generic +function, all the methods of this generic function will be grabbed and +the most specific among them will be applied. We say that a method +@var{M} is @emph{more specific} than a method @var{M'} if the class of +its parameters are more specific than the @var{M'} ones. To be more +precise, when a generic function must be ``called'' the system will: + +@cindex generic function +@enumerate +@item +search among all the generic function those which are applicable +@item +sort the list of applicable methods in the ``most specific'' order +@item +call the most specific method of this list (i.e. the first method of +the sorted methods list). +@end enumerate + +The definition of a generic function is done with the +@code{define-generic} macro. Definition of a new method is done with the +@code{define-method} macro. Note that @code{define-method} automatically +defines the generic function if it has not been defined +before. Consequently, most of the time, the @code{define-generic} needs +not be used. +@findex define-generic +@findex define-method +Consider the following definitions: + +@lisp +(define-generic G) +(define-method (G (a ) b) 'integer) +(define-method (G (a ) b) 'real) +(define-method (G a b) 'top) +@end lisp + +The @code{define-generic} call defines @var{G} as a generic +function. Note that the signature of the generic function is not given +upon definition, contrarily to CLOS. This will permit methods with +different signatures for a given generic function, as we shall see +later. The three next lines define methods for the @var{G} generic +function. Each method uses a sequence of @dfn{parameter specializers} +that specify when the given method is applicable. A specializer permits +to indicate the class a parameter must belong to (directly or +indirectly) to be applicable. If no specializer is given, the system +defaults it to @code{}. Thus, the first method definition is +equivalent to + +@cindex parameter specializers +@lisp +(define-method (G (a ) (b )) 'integer) +@end lisp + +Now, let us look at some possible calls to generic function @var{G}: + +@lisp +(G 2 3) @result{} integer +(G 2 #t) @result{} integer +(G 1.2 'a) @result{} real +@c (G #3 'a) @result{} real @c was {\sharpsign} +(G #t #f) @result{} top +(G 1 2 3) @result{} error (since no method exists for 3 parameters) +@end lisp + +The preceding methods use only one specializer per parameter list. Of +course, each parameter can use a specializer. In this case, the +parameter list is scanned from left to right to determine the +applicability of a method. Suppose we declare now + +@lisp +(define-method (G (a ) (b )) 'integer-number) +(define-method (G (a ) (b )) 'integer-real) +(define-method (G (a ) (b )) 'integer-integer) +(define-method (G a (b )) 'top-number) +@end lisp + +In this case, + +@lisp +(G 1 2) @result{} integer-integer +(G 1 1.0) @result{} integer-real +(G 1 #t) @result{} integer +(G 'a 1) @result{} top-number +@end lisp + +@node Next-method, Example, Generic functions and methods, Generic functions +@subsection Next-method + +When a generic function is called, the list of applicable methods is +built. As mentioned before, the most specific method of this list is +applied (see@ @ref{Generic functions and methods}). This method may call +the next method in the list of applicable methods. This is done by using +the special form @code{next-method}. Consider the following definitions + +@lisp +(define-method (Test (a )) (cons 'integer (next-method))) +(define-method (Test (a )) (cons 'number (next-method))) +(define-method (Test a) (list 'top)) +@end lisp + +With those definitions, + +@lisp +(Test 1) @result{} (integer number top) +(Test 1.0) @result{} (number top) +(Test #t) @result{} (top) +@end lisp + +@node Example, , Next-method, Generic functions +@subsection Example + +In this section we shall continue to define operations on the @code{} +class defined in Figure@ 2. Suppose that we want to use it to implement +complex numbers completely. For instance a definition for the addition of +two complexes could be + +@lisp +(define-method (new-+ (a ) (b )) + (make-rectangular (+ (real-part a) (real-part b)) + (+ (imag-part a) (imag-part b)))) +@end lisp + +To be sure that the @code{+} used in the method @code{new-+} is the standard +addition we can do: + +@lisp +(define-generic new-+) + +(let ((+ +)) + (define-method (new-+ (a ) (b )) + (make-rectangular (+ (real-part a) (real-part b)) + (+ (imag-part a) (imag-part b))))) +@end lisp + +The @code{define-generic} ensures here that @code{new-+} will be defined +in the global environment. Once this is done, we can add methods to the +generic function @code{new-+} which make a closure on the @code{+} +symbol. A complete writing of the @code{new-+} methods is shown in +Figure@ 3. + +@example +@group +@lisp +(define-generic new-+) + +(let ((+ +)) + + (define-method (new-+ (a ) (b )) (+ a b)) + + (define-method (new-+ (a ) (b )) + (make-rectangular (+ a (real-part b)) (imag-part b))) + + (define-method (new-+ (a ) (b )) + (make-rectangular (+ (real-part a) b) (imag-part a))) + + (define-method (new-+ (a ) (b )) + (make-rectangular (+ (real-part a) (real-part b)) + (+ (imag-part a) (imag-part b)))) + + (define-method (new-+ (a )) a) + + (define-method (new-+) 0) + + (define-method (new-+ . args) + (new-+ (car args) + (apply new-+ (cdr args))))) + +(set! + new-+) +@end lisp + +@center @emph{Fig 3: Extending @code{+} for dealing with complex numbers} +@end group +@end example + +@sp 3 +We use here the fact that generic function are not obliged to have the +same number of parameters, contrarily to CLOS. The four first methods +implement the dyadic addition. The fifth method says that the addition +of a single element is this element itself. The sixth method says that +using the addition with no parameter always return 0. The last method +takes an arbitrary number of parameters@footnote{The parameter list for +a @code{define-method} follows the conventions used for Scheme +procedures. In particular it can use the dot notation or a symbol to +denote an arbitrary number of parameters}. This method acts as a kind +of @code{reduce}: it calls the dyadic addition on the @emph{car} of the +list and on the result of applying it on its rest. To finish, the +@code{set!} permits to redefine the @code{+} symbol to our extended +addition. + +@sp 3 +To terminate our implementation (integration?) of complex numbers, we can +redefine standard Scheme predicates in the following manner: + +@lisp +(define-method (complex? c ) #t) +(define-method (complex? c) #f) + +(define-method (number? n ) #t) +(define-method (number? n) #f) +@dots{} +@dots{} +@end lisp + +Standard primitives in which complex numbers are involved could also be +redefined in the same manner. + diff --git a/doc/goops/goops.texi b/doc/goops/goops.texi new file mode 100644 index 000000000..580b120e0 --- /dev/null +++ b/doc/goops/goops.texi @@ -0,0 +1,2788 @@ +\input texinfo +@c -*-texinfo-*- +@c %**start of header +@setfilename goops.info +@settitle Goops Manual +@set goops +@setchapternewpage odd +@paragraphindent 0 +@c %**end of header + +@set VERSION 0.3 + +@dircategory The Algorithmic Language Scheme +@direntry +* GOOPS: (goops). The GOOPS reference manual. +@end direntry + +@macro goops +GOOPS +@end macro + +@macro guile +Guile +@end macro + +@ifinfo +This file documents GOOPS, an object oriented extension for Guile. + +Copyright (C) 1999, 2000, 2001 Free Software Foundation + +Permission is granted to make and distribute verbatim copies of +this manual provided the copyright notice and this permission notice +are preserved on all copies. + +@end ifinfo + +@c This title page illustrates only one of the +@c two methods of forming a title page. + +@titlepage +@title Goops Manual +@subtitle For use with GOOPS @value{VERSION} +@include ../AUTHORS + +@c The following two commands +@c start the copyright page. +@page +@vskip 0pt plus 1filll +Copyright @copyright{} 1999 Free Software Foundation + +Permission is granted to make and distribute verbatim copies of +this manual provided the copyright notice and this permission notice +are preserved on all copies. + +@end titlepage + +@node Top, Introduction, (dir), (dir) + +@menu +[When the manual is completed, this will be a flat index in the style of + the Emacs manual. More nodes will turn up under parts I-III.] + +Part I: Preliminaries + +* Introduction:: +* Getting Started:: + +Part II: Reference Manual + +* Reference Manual:: + +Part III: GOOPS Meta Object Protocol + +* MOP Specification:: + +The GOOPS tutorial + +* Tutorial:: + +* Index:: +* Concept Index:: +* Function and Variable Index:: +@end menu + +@iftex +@chapter Preliminaries +@end iftex + +@node Introduction, Getting Started, Top, Top +@section Introduction + +@goops{} is the object oriented extension to @guile{}. Its +implementation is derived from @w{STk-3.99.3} by Erick Gallesio and +version 1.3 of Gregor Kiczales @cite{Tiny-Clos}. It is very close in +spirit to CLOS, the Common Lisp Object System (@cite{CLtL2}) but is +adapted for the Scheme language. While GOOPS is not compatible with any +of these systems, GOOPS contains a compatibility module which allows for +execution of STKlos programs. + +Briefly stated, the @goops{} extension gives the user a full object +oriented system with multiple inheritance and generic functions with +multi-method dispatch. Furthermore, the implementation relies on a true +meta object protocol, in the spirit of the one defined for CLOS +(@cite{Gregor Kiczales: A Metaobject Protocol}). + +@node Getting Started, Reference Manual, Introduction, Top +@section Getting Started + +@menu +* Running GOOPS:: + +Examples of some basic GOOPS functionality. + +* Methods:: +* User-defined types:: +* Asking for the type of an object:: + +See further in the GOOPS tutorial available in this distribution in +info (goops.info) and texinfo format. +@end menu + +@node Running GOOPS, Methods, Getting Started, Getting Started +@subsection Running GOOPS + +@enumerate +@item +Type + +@smalllisp +guile-oops +@end smalllisp + +You should now be at the Guile prompt ("guile> "). + +@item +Type + +@smalllisp +(use-modules (oop goops)) +@end smalllisp + +to load GOOPS. (If your system supports dynamic loading, you +should be able to do this not only from `guile-oops' but from an +arbitrary Guile interpreter.) +@end enumerate + +We're now ready to try some basic GOOPS functionality. + +@node Methods, User-defined types, Running GOOPS, Getting Started +@subsection Methods + +@smalllisp +@group +(define-method (+ (x ) (y )) + (string-append x y)) + +(+ 1 2) --> 3 +(+ "abc" "de") --> "abcde" +@end group +@end smalllisp + +@node User-defined types, Asking for the type of an object, Methods, Getting Started +@subsection User-defined types + +@smalllisp +(define-class <2D-vector> () + (x #:init-value 0 #:accessor x-component #:init-keyword #:x) + (y #:init-value 0 #:accessor y-component #:init-keyword #:y)) + +@group +(use-modules (ice-9 format)) + +(define-method (write (obj <2D-vector>) port) + (display (format #f "<~S, ~S>" (x-component obj) (y-component obj)) + port)) + +(define v (make <2D-vector> #:x 3 #:y 4)) + +v --> <3, 4> +@end group + +@group +(define-method (+ (x <2D-vector>) (y <2D-vector>)) + (make <2D-vector> + #:x (+ (x-component x) (x-component y)) + #:y (+ (y-component x) (y-component y)))) + +(+ v v) --> <6, 8> +@end group +@end smalllisp + +@node Asking for the type of an object, , User-defined types, Getting Started +@subsection Types + +@example +(class-of v) --> #< <2D-vector> 40241ac0> +<2D-vector> --> #< <2D-vector> 40241ac0> +(class-of 1) --> #< 401b2a98> + --> #< 401b2a98> + +(is-a? v <2D-vector>) --> #t +@end example + +@node Reference Manual, MOP Specification, Getting Started, Top +@chapter Reference Manual + +This chapter is the GOOPS reference manual. It aims to describe all the +syntax, procedures, options and associated concepts that a typical +application author would need to understand in order to use GOOPS +effectively in their application. It also describes what is meant by +the GOOPS ``metaobject protocol'' (aka ``MOP''), and indicates how +authors can use the metaobject protocol to customize the behaviour of +GOOPS itself. + +For a detailed specification of the GOOPS metaobject protocol, see +@ref{MOP Specification}. + +@menu +* Introductory Remarks:: +* Defining New Classes:: +* Creating Instances:: +* Accessing Slots:: +* Creating Generic Functions:: +* Adding Methods to Generic Functions:: +* Invoking Generic Functions:: +* Redefining a Class:: +* Changing the Class of an Instance:: +* Introspection:: +* Miscellaneous Functions:: +@end menu + +@node Introductory Remarks +@section Introductory Remarks + +GOOPS is an object-oriented programming system based on a ``metaobject +protocol'' derived from the ones used in CLOS (the Common Lisp Object +System), tiny-clos (a small Scheme implementation of a subset of CLOS +functionality) and STKlos. + +GOOPS can be used by application authors at a basic level without any +need to understand what the metaobject protocol (aka ``MOP'') is and how +it works. On the other hand, the MOP underlies even the customizations +that application authors are likely to make use of very quickly --- such +as defining an @code{initialize} method to customize the initialization +of instances of an application-defined class --- and an understanding of +the MOP makes it much easier to explain such customizations in a precise +way. And in the long run, understanding the MOP is the key both to +understanding GOOPS at a deeper level and to taking full advantage of +GOOPS' power, by customizing the behaviour of GOOPS itself. + +Each of the following sections of the reference manual is arranged +such that the most basic usage is introduced first, and then subsequent +subsections discuss the related internal functions and metaobject +protocols, finishing with a description of how to customize that area of +functionality. + +These introductory remarks continue with a few words about metaobjects +and the MOP. Readers who do not want to be bothered yet with the MOP +and customization could safely skip this subsection on a first reading, +and should correspondingly skip subsequent subsections that are +concerned with internals and customization. + +In general, this reference manual assumes familiarity with standard +object oriented concepts and terminology. However, some of the terms +used in GOOPS is less well known, so the Terminology subsection +provides definitions for these terms. + +@menu +* Metaobjects and the Metaobject Protocol:: +* Terminology:: +@end menu + +@node Metaobjects and the Metaobject Protocol +@subsection Metaobjects and the Metaobject Protocol + +The conceptual building blocks of GOOPS are classes, slot definitions, +instances, generic functions and methods. A class is a grouping of +inheritance relations and slot definitions. An instance is an object +with slots that are allocated following the rules implied by its class's +superclasses and slot definitions. A generic function is a collection +of methods and rules for determining which of those methods to apply +when the generic function is invoked. A method is a procedure and a set +of specializers that specify the type of arguments to which the +procedure is applicable. + +Of these entities, GOOPS represents classes, generic functions and +methods as ``metaobjects''. In other words, the values in a GOOPS +program that describe classes, generic functions and methods, are +themselves instances (or ``objects'') of special GOOPS classes that +encapsulate the behaviour, respectively, of classes, generic functions, +and methods. + +(The other two entities are slot definitions and instances. Slot +definitions are not strictly instances, but every slot definition is +associated with a GOOPS class that specifies the behaviour of the slot +as regards accessibility and protection from garbage collection. +Instances are of course objects in the usual sense, and there is no +benefit from thinking of them as metaobjects.) + +The ``metaobject protocol'' (aka ``MOP'') is the specification of the +generic functions which determine the behaviour of these metaobjects and +the circumstances in which these generic functions are invoked. + +For a concrete example of what this means, consider how GOOPS calculates +the set of slots for a class that is being defined using +@code{define-class}. The desired set of slots is the union of the new +class's direct slots and the slots of all its superclasses. But +@code{define-class} itself does not perform this calculation. Instead, +there is a method of the @code{initialize} generic function that is +specialized for instances of type @code{}, and it is this method +that performs the slot calculation. + +@code{initialize} is a generic function which GOOPS calls whenever a new +instance is created, immediately after allocating memory for a new +instance, in order to initialize the new instance's slots. The sequence +of steps is as follows. + +@itemize @bullet +@item +@code{define-class} uses @code{make} to make a new instance of the +@code{}, passing as initialization arguments the superclasses, +slot definitions and class options that were specified in the +@code{define-class} form. + +@item +@code{make} allocates memory for the new instance, and then invokes the +@code{initialize} generic function to initialize the new instance's +slots. + +@item +The @code{initialize} generic function applies the method that is +specialized for instances of type @code{}, and this method +performs the slot calculation. +@end itemize + +In other words, rather than being hardcoded in @code{define-class}, the +behaviour of class definition is encapsulated by generic function +methods that are specialized for the class @code{}. + +It is possible to create a new class that inherits from @code{}, +which is called a ``metaclass'', and to write a new @code{initialize} +method that is specialized for instances of the new metaclass. Then, if +the @code{define-class} form includes a @code{#:metaclass} class option +whose value is the new metaclass, the class that is defined by the +@code{define-class} form will be an instance of the new metaclass rather +than of the default @code{}, and will be defined in accordance +with the new @code{initialize} method. Thus the default slot +calculation, as well as any other aspect of the new class's relationship +with its superclasses, can be modified or overridden. + +In a similar way, the behaviour of generic functions can be modified or +overridden by creating a new class that inherits from the standard +generic function class @code{}, writing appropriate methods +that are specialized to the new class, and creating new generic +functions that are instances of the new class. + +The same is true for method metaobjects. And the same basic mechanism +allows the application class author to write an @code{initialize} method +that is specialized to their application class, to initialize instances +of that class. + +Such is the power of the MOP. Note that @code{initialize} is just one +of a large number of generic functions that can be customized to modify +the behaviour of application objects and classes and of GOOPS itself. +Each subsequent section of the reference manual covers a particular area +of GOOPS functionality, and describes the generic functions that are +relevant for customization of that area. + +We conclude this subsection by emphasizing a point that may seem +obvious, but contrasts with the corresponding situation in some other +MOP implementations, such as CLOS. The point is simply that an +identifier which represents a GOOPS class or generic function is a +variable with a first-class value, the value being an instance of class +@code{} or @code{}. (In CLOS, on the other hand, a +class identifier is a symbol that indexes the corresponding class +metaobject in a separate namespace for classes.) This is, of course, +simply an extension of the tendency in Scheme to avoid the unnecessary +use of, on the one hand, syntactic forms that require unevaluated +arguments and, on the other, separate identifier namespaces (e.g. for +class names), but it is worth noting that GOOPS conforms fully to this +Schemely principle. + +@node Terminology +@subsection Terminology + +It is assumed that the reader is already familiar with standard object +orientation concepts such as classes, objects/instances, +inheritance/subclassing, generic functions and methods, encapsulation +and polymorphism. + +This section explains some of the less well known concepts and +terminology that GOOPS uses, which are assumed by the following sections +of the reference manual. + +@menu +* Metaclass:: +* Class Precedence List:: +* Accessor:: +@end menu + +@node Metaclass +@subsubsection Metaclass + +A @dfn{metaclass} is the class of an object which represents a GOOPS +class. Put more succinctly, a metaclass is a class's class. + +Most GOOPS classes have the metaclass @code{} and, by default, +any new class that is created using @code{define-class} has the +metaclass @code{}. + +But what does this really mean? To find out, let's look in more detail +at what happens when a new class is created using @code{define-class}: + +@example +(define-class () . slots) +@end example + +GOOPS actually expands the @code{define-class} form to something like +this + +@example +(define (class () . slots)) +@end example + +and thence to + +@example +(define + (make #:supers (list ) #:slots slots)) +@end example + +In other words, the value of @code{} is in fact an instance of +the class @code{} with slot values specifying the superclasses +and slot definitions for the class @code{}. (@code{#:supers} +and @code{#:slots} are initialization keywords for the @code{dsupers} +and @code{dslots} slots of the @code{} class.) + +In order to take advantage of the full power of the GOOPS metaobject +protocol (@pxref{MOP Specification}), it is sometimes desirable to +create a new class with a metaclass other than the default +@code{}. This is done by writing: + +@example +(define-class () + slot @dots{} + #:metaclass ) +@end example + +GOOPS expands this to something like: + +@example +(define + (make #:supers (list ) #:slots slots)) +@end example + +In this case, the value of @code{} is an instance of the more +specialized class @code{}. Note that +@code{} itself must previously have been defined as a +subclass of @code{}. For a full discussion of when and how it is +useful to define new metaclasses, see @ref{MOP Specification}. + +Now let's make an instance of @code{}: + +@example +(define my-object (make ...)) +@end example + +All of the following statements are correct expressions of the +relationships between @code{my-object}, @code{}, +@code{} and @code{}. + +@itemize @bullet +@item +@code{my-object} is an instance of the class @code{}. + +@item +@code{} is an instance of the class @code{}. + +@item +@code{} is an instance of the class @code{}. + +@item +The class of @code{my-object} is @code{}. + +@item +The metaclass of @code{my-object} is @code{}. + +@item +The class of @code{} is @code{}. + +@item +The metaclass of @code{} is @code{}. + +@item +The class of @code{} is @code{}. + +@item +The metaclass of @code{} is @code{}. + +@item +@code{} is not a metaclass, since it is does not inherit from +@code{}. + +@item +@code{} is a metaclass, since it inherits from +@code{}. +@end itemize + +@node Class Precedence List +@subsubsection Class Precedence List + +The @dfn{class precedence list} of a class is the list of all direct and +indirect superclasses of that class, including the class itself. + +In the absence of multiple inheritance, the class precedence list is +ordered straightforwardly, beginning with the class itself and ending +with @code{}. + +For example, given this inheritance hierarchy: + +@example +(define-class () @dots{}) +(define-class () @dots{}) +(define-class () @dots{}) +@end example + +the class precedence list of would be + +@example +( ) +@end example + +With multiple inheritance, the algorithm is a little more complicated. +A full description is provided by the GOOPS Tutorial: see @ref{Class +precedence list}. + +``Class precedence list'' is often abbreviated, in documentation and +Scheme variable names, to @dfn{cpl}. + +@node Accessor +@subsubsection Accessor + +An @dfn{accessor} is a generic function with both reference and setter +methods. + +@example +(define-accessor perimeter) +@end example + +Reference methods for an accessor are defined in the same way as generic +function methods. + +@example +(define-method (perimeter (s )) + (* 4 (side-length s))) +@end example + +Setter methods for an accessor are defined by specifying ``(setter +)'' as the first parameter of the @code{define-method} +call. + +@example +(define-method ((setter perimeter) (s ) (n )) + (set! (side-length s) (/ n 4))) +@end example + +Once an appropriate setter method has been defined in this way, it can +be invoked using the generalized @code{set!} syntax, as in: + +@example +(set! (perimeter s1) 18.3) +@end example + +@node Defining New Classes +@section Defining New Classes + +[ *fixme* Somewhere in this manual there needs to be an introductory +discussion about GOOPS classes, generic functions and methods, covering + +@itemize @bullet +@item +how classes encapsulate related items of data in @dfn{slots} + +@item +why it is that, unlike in C++ and Java, a class does not encapsulate the +methods that act upon the class (at least not in the C++/Java sense) + +@item +how generic functions provide a more general solution that provides for +dispatch on all argument types, and avoids idiosyncracies like C++'s +friend classes + +@item +how encapsulation in the sense of data- and code-hiding, or of +distinguishing interface from implementation, is treated in Guile as an +orthogonal concept to object orientation, and is the responsibility of +the module system. +@end itemize + +Some of this is covered in the Tutorial chapter, in @ref{Generic +functions and methods} - perhaps the best solution would be to expand +the discussion there. ] + +@menu +* Basic Class Definition:: +* Class Options:: +* Slot Options:: +* Class Definition Internals:: +* Customizing Class Definition:: +* STKlos Compatibility:: +@end menu + +@node Basic Class Definition +@subsection Basic Class Definition + +New classes are defined using the @code{define-class} syntax, with +arguments that specify the classes that the new class should inherit +from, the direct slots of the new class, and any required class options. + +@deffn syntax define-class name (super @dots{}) slot-definition @dots{} . options +Define a class called @var{name} that inherits from @var{super}s, with +direct slots defined by @var{slot-definition}s and class options +@var{options}. The newly created class is bound to the variable name +@var{name} in the current environment. + +Each @var{slot-definition} is either a symbol that names the slot or a +list, + +@example +(@var{slot-name-symbol} . @var{slot-options}) +@end example + +where @var{slot-name-symbol} is a symbol and @var{slot-options} is a +list with an even number of elements. The even-numbered elements of +@var{slot-options} (counting from zero) are slot option keywords; the +odd-numbered elements are the corresponding values for those keywords. + +@var{options} is a similarly structured list containing class option +keywords and corresponding values. +@end deffn + +The standard GOOPS class and slot options are described in the following +subsections: see @ref{Class Options} and @ref{Slot Options}. + +Example 1. Define a class that combines two pre-existing classes by +inheritance but adds no new slots. + +@example +(define-class ( )) +@end example + +Example 2. Define a @code{regular-polygon} class with slots for side +length and number of sides that have default values and can be accessed +via the generic functions @code{side-length} and @code{num-sides}. + +@example +(define-class () + (sl #:init-value 1 #:accessor side-length) + (ns #:init-value 5 #:accessor num-sides)) +@end example + +Example 3. Define a class whose behavior (and that of its instances) is +customized via an application-defined metaclass. + +@example +(define-class () + (s #:init-value #f #:accessor state) + ... + #:metaclass ) +@end example + +@node Class Options +@subsection Class Options + +@deffn {class option} #:metaclass metaclass +The @code{#:metaclass} class option specifies the metaclass of the class +being defined. @var{metaclass} must be a class that inherits from +@code{}. For an introduction to the use of metaclasses, see +@ref{Metaobjects and the Metaobject Protocol} and @ref{Metaclass}. + +If the @code{#:metaclass} option is absent, GOOPS reuses or constructs a +metaclass for the new class by calling @code{ensure-metaclass} +(@pxref{Class Definition Internals,, ensure-metaclass}). +@end deffn + +@deffn {class option} #:name name +The @code{#:name} class option specifies the new class's name. This +name is used to identify the class whenever related objects - the class +itself, its instances and its subclasses - are printed. + +If the @code{#:name} option is absent, GOOPS uses the first argument to +@code{define-class} as the class name. +@end deffn + +@deffn {class option} #:environment environment +*fixme* Not sure about this one, but I think that the +@code{#:environment} option specifies the environment in which the +class's getters and setters are computed and evaluated. + +If the @code{#:environment} option is not specified, the class's +environment defaults to the top-level environment in which the +@code{define-class} form appears. +@end deffn + +@node Slot Options +@subsection Slot Options + +@deffn {slot option} #:allocation allocation +The @code{#:allocation} option tells GOOPS how to allocate storage for +the slot. Possible values for @var{allocation} are + +@itemize @bullet +@item @code{#:instance} + +Indicates that GOOPS should create separate storage for this slot in +each new instance of the containing class (and its subclasses). + +@item @code{#:class} + +Indicates that GOOPS should create storage for this slot that is shared +by all instances of the containing class (and its subclasses). In other +words, a slot in class @var{C} with allocation @code{#:class} is shared +by all @var{instance}s for which @code{(is-a? @var{instance} @var{c})}. + +@item @code{#:each-subclass} + +Indicates that GOOPS should create storage for this slot that is shared +by all @emph{direct} instances of the containing class, and that +whenever a subclass of the containing class is defined, GOOPS should +create a new storage for the slot that is shared by all @emph{direct} +instances of the subclass. In other words, a slot with allocation +@code{#:each-subclass} is shared by all instances with the same +@code{class-of}. + +@item @code{#:virtual} + +Indicates that GOOPS should not allocate storage for this slot. The +slot definition must also include the @code{#:slot-ref} and +@code{#:slot-set!} options to specify how to reference and set the value +for this slot. +@end itemize + +The default value is @code{#:instance}. + +Slot allocation options are processed when defining a new class by the +generic function @code{compute-get-n-set}, which is specialized by the +class's metaclass. Hence new types of slot allocation can be +implemented by defining a new metaclass and a method for +@code{compute-get-n-set} that is specialized for the new metaclass. For +an example of how to do this, see @ref{Customizing Class Definition}. +@end deffn + +@deffn {slot option} #:slot-ref getter +@deffnx {slot option} #:slot-set! setter +The @code{#:slot-ref} and @code{#:slot-set!} options must be specified +if the slot allocation is @code{#:virtual}, and are ignored otherwise. + +@var{getter} should be a closure taking a single @var{instance} parameter +that returns the current slot value. @var{setter} should be a closure +taking two parameters - @var{instance} and @var{new-val} - that sets the +slot value to @var{new-val}. +@end deffn + +@deffn {slot option} #:getter getter +@deffnx {slot option} #:setter setter +@deffnx {slot option} #:accessor accessor +These options, if present, tell GOOPS to create generic function and +method definitions that can be used to get and set the slot value more +conveniently than by using @code{slot-ref} and @code{slot-set!}. + +@var{getter} specifies a generic function to which GOOPS will add a +method for getting the slot value. @var{setter} specifies a generic +function to which GOOPS will add a method for setting the slot value. +@var{accessor} specifies an accessor to which GOOPS will add methods for +both getting and setting the slot value. + +So if a class includes a slot definition like this: + +@example +(c #:getter get-count #:setter set-count #:accessor count) +@end example + +GOOPS defines generic function methods such that the slot value can be +referenced using either the getter or the accessor - + +@example +(let ((current-count (get-count obj))) @dots{}) +(let ((current-count (count obj))) @dots{}) +@end example + +- and set using either the setter or the accessor - + +@example +(set-count obj (+ 1 current-count)) +(set! (count obj) (+ 1 current-count)) +@end example + +Note that + +@itemize @bullet +@item +with an accessor, the slot value is set using the generalized +@code{set!} syntax + +@item +in practice, it is unusual for a slot to use all three of these options: +read-only, write-only and read-write slots would typically use only +@code{#:getter}, @code{#:setter} and @code{#:accessor} options +respectively. +@end itemize + +If the specified names are already bound in the top-level environment to +values that cannot be upgraded to generic functions, those values are +overwritten during evaluation of the @code{define-class} that contains +the slot definition. For details, see @ref{Generic Function Internals,, +ensure-generic}. +@end deffn + +@deffn {slot option} #:init-value init-value +@deffnx {slot option} #:init-form init-form +@deffnx {slot option} #:init-thunk init-thunk +@deffnx {slot option} #:init-keyword init-keyword +These options provide various ways to specify how to initialize the +slot's value at instance creation time. @var{init-value} is a fixed +value. @var{init-thunk} is a procedure of no arguments that is called +when a new instance is created and should return the desired initial +slot value. @var{init-form} is an unevaluated expression that gets +evaluated when a new instance is created and should return the desired +initial slot value. @var{init-keyword} is a keyword that can be used to +pass an initial slot value to @code{make} when creating a new instance. + +If more than one of these options is specified for the same slot, the +order of precedence, highest first is + +@itemize @bullet +@item +@code{#:init-keyword}, if @var{init-keyword} is present in the options +passed to @code{make} + +@item +@code{#:init-thunk}, @code{#:init-form} or @code{#:init-value}. +@end itemize + +If the slot definition contains more than one initialization option of +the same precedence, the later ones are ignored. If a slot is not +initialized at all, its value is unbound. + +In general, slots that are shared between more than one instance are +only initialized at new instance creation time if the slot value is +unbound at that time. However, if the new instance creation specifies +a valid init keyword and value for a shared slot, the slot is +re-initialized regardless of its previous value. + +Note, however, that the power of GOOPS' metaobject protocol means that +everything written here may be customized or overridden for particular +classes! The slot initializations described here are performed by the least +specialized method of the generic function @code{initialize}, whose +signature is + +@example +(define-method (initialize (object ) initargs) ...) +@end example + +The initialization of instances of any given class can be customized by +defining a @code{initialize} method that is specialized for that class, +and the author of the specialized method may decide to call +@code{next-method} - which will result in a call to the next less +specialized @code{initialize} method - at any point within the +specialized code, or maybe not at all. In general, therefore, the +initialization mechanisms described here may be modified or overridden by +more specialized code, or may not be supported at all for particular +classes. +@end deffn + +@node Class Definition Internals +@subsection Class Definition Internals + +Implementation notes: @code{define-class} expands to an expression which + +@itemize @bullet +@item +checks that it is being evaluated only at top level + +@item +defines any accessors that are implied by the @var{slot-definition}s + +@item +uses @code{class} to create the new class (@pxref{Class Definition +Internals,, class}) + +@item +checks for a previous class definition for @var{name} and, if found, +handles the redefinition by invoking @code{class-redefinition} +(@pxref{Redefining a Class}). +@end itemize + +@deffn syntax class name (super @dots{}) slot-definition @dots{} . options +Return a newly created class that inherits from @var{super}s, with +direct slots defined by @var{slot-definition}s and class options +@var{options}. For the format of @var{slot-definition}s and +@var{options}, see @ref{Basic Class Definition,, define-class}. +@end deffn + +Implementation notes: @code{class} expands to an expression which + +@itemize @bullet +@item +processes the class and slot definition options to check that they are +well-formed, to convert the @code{#:init-form} option to an +@code{#:init-thunk} option, to supply a default environment parameter +(the current top-level environment) and to evaluate all the bits that +need to be evaluated + +@item +calls @code{make-class} to create the class with the processed and +evaluated parameters. +@end itemize + +@deffn procedure make-class supers slots . options +Return a newly created class that inherits from @var{supers}, with +direct slots defined by @var{slots} and class options @var{options}. +For the format of @var{slots} and @var{options}, see @ref{Basic Class +Definition,, define-class}, except note that for @code{make-class}, +@var{slots} and @var{options} are separate list parameters: @var{slots} +here is a list of slot definitions. +@end deffn + +Implementation notes: @code{make-class} + +@itemize @bullet +@item +adds @code{} to the @var{supers} list if @var{supers} is empty +or if none of the classes in @var{supers} have @code{} in their +class precedence list + +@item +defaults the @code{#:environment}, @code{#:name} and @code{#:metaclass} +options, if they are not specified by @var{options}, to the current +top-level environment, the unbound value, and @code{(ensure-metaclass +@var{supers})} respectively (@pxref{Class Definition Internals,, +ensure-metaclass}) + +@item +checks for duplicate classes in @var{supers} and duplicate slot names in +@var{slots}, and signals an error if there are any duplicates + +@item +calls @code{make}, passing the metaclass as the first parameter and all +other parameters as option keywords with values. +@end itemize + +@deffn procedure ensure-metaclass supers env +Return a metaclass suitable for a class that inherits from the list of +classes in @var{supers}. The returned metaclass is the union by +inheritance of the metaclasses of the classes in @var{supers}. + +In the simplest case, where all the @var{supers} are straightforward +classes with metaclass @code{}, the returned metaclass is just +@code{}. + +For a more complex example, suppose that @var{supers} contained one +class with metaclass @code{} and one with metaclass +@code{}. Then the returned metaclass would be a +class that inherits from both @code{} and +@code{}. + +If @var{supers} is the empty list, @code{ensure-metaclass} returns the +default GOOPS metaclass @code{}. + +GOOPS keeps a list of the metaclasses created by +@code{ensure-metaclass}, so that each required type of metaclass only +has to be created once. + +The @code{env} parameter is ignored. +@end deffn + +@deffn procedure ensure-metaclass-with-supers meta-supers +@code{ensure-metaclass-with-supers} is an internal procedure used by +@code{ensure-metaclass} (@pxref{Class Definition Internals,, +ensure-metaclass}). It returns a metaclass that is the union by +inheritance of the metaclasses in @var{meta-supers}. +@end deffn + +The internals of @code{make}, which is ultimately used to create the new +class object, are described in @ref{Customizing Instance Creation}, +which covers the creation and initialization of instances in general. + +@node Customizing Class Definition +@subsection Customizing Class Definition + +During the initialization of a new class, GOOPS calls a number of generic +functions with the newly allocated class instance as the first +argument. Specifically, GOOPS calls the generic function + +@itemize @bullet +@item +(initialize @var{class} @dots{}) +@end itemize + +where @var{class} is the newly allocated class instance, and the default +@code{initialize} method for arguments of type @code{} calls the +generic functions + +@itemize @bullet +@item +(compute-cpl @var{class}) + +@item +(compute-slots @var{class}) + +@item +(compute-get-n-set @var{class} @var{slot-def}), for each of the slot +definitions returned by @code{compute-slots} + +@item +(compute-getter-method @var{class} @var{slot-def}), for each of the +slot definitions returned by @code{compute-slots} that includes a +@code{#:getter} or @code{#:accessor} slot option + +@item +(compute-setter-method @var{class} @var{slot-def}), for each of the +slot definitions returned by @code{compute-slots} that includes a +@code{#:setter} or @code{#:accessor} slot option. +@end itemize + +If the metaclass of the new class is something more specialized than the +default @code{}, then the type of @var{class} in the calls above +is more specialized than @code{}, and hence it becomes possible +to define generic function methods, specialized for the new class's +metaclass, that can modify or override the default behaviour of +@code{initialize}, @code{compute-cpl} or @code{compute-get-n-set}. + +@code{compute-cpl} computes the class precedence list (``CPL'') for the +new class (@pxref{Class precedence list}), and returns it as a list of +class objects. The CPL is important because it defines a superclass +ordering that is used, when a generic function is invoked upon an +instance of the class, to decide which of the available generic function +methods is the most specific. Hence @code{compute-cpl} could be +customized in order to modify the CPL ordering algorithm for all classes +with a special metaclass. + +The default CPL algorithm is encapsulated by the @code{compute-std-cpl} +procedure, which is in turn called by the default @code{compute-cpl} +method. + +@deffn procedure compute-std-cpl class +Compute and return the class precedence list for @var{class} according +to the algorithm described in @ref{Class precedence list}. +@end deffn + +@code{compute-slots} computes and returns a list of all slot definitions +for the new class. By default, this list includes the direct slot +definitions from the @code{define-class} form, plus the slot definitions +that are inherited from the new class's superclasses. The default +@code{compute-slots} method uses the CPL computed by @code{compute-cpl} +to calculate this union of slot definitions, with the rule that slots +inherited from superclasses are shadowed by direct slots with the same +name. One possible reason for customizing @code{compute-slots} would be +to implement an alternative resolution strategy for slot name conflicts. + +@code{compute-get-n-set} computes the low-level closures that will be +used to get and set the value of a particular slot, and returns them in +a list with two elements. + +The closures returned depend on how storage for that slot is allocated. +The standard @code{compute-get-n-set} method, specialized for classes of +type @code{}, handles the standard GOOPS values for the +@code{#:allocation} slot option (@pxref{Slot Options,, allocation}). By +defining a new @code{compute-get-n-set} method for a more specialized +metaclass, it is possible to support new types of slot allocation. + +Suppose you wanted to create a large number of instances of some class +with a slot that should be shared between some but not all instances of +that class - say every 10 instances should share the same slot storage. +The following example shows how to implement and use a new type of slot +allocation to do this. + +@example +(define-class ()) + +(let ((batch-allocation-count 0) + (batch-get-n-set #f)) + (define-method (compute-get-n-set (class ) s) + (case (slot-definition-allocation s) + ((#:batched) + ;; If we've already used the same slot storage for 10 instances, + ;; reset variables. + (if (= batch-allocation-count 10) + (begin + (set! batch-allocation-count 0) + (set! batch-get-n-set #f))) + ;; If we don't have a current pair of get and set closures, + ;; create one. make-closure-variable returns a pair of closures + ;; around a single Scheme variable - see goops.scm for details. + (or batch-get-n-set + (set! batch-get-n-set (make-closure-variable))) + ;; Increment the batch allocation count. + (set! batch-allocation-count (+ batch-allocation-count 1)) + batch-get-n-set) + + ;; Call next-method to handle standard allocation types. + (else (next-method))))) + +(define-class () + ... + (c #:allocation #:batched) + ... + #:metaclass ) +@end example + +The usage of @code{compute-getter-method} and @code{compute-setter-method} +is described in @ref{MOP Specification}. + +@code{compute-cpl} and @code{compute-get-n-set} are called by the +standard @code{initialize} method for classes whose metaclass is +@code{}. But @code{initialize} itself can also be modified, by +defining an @code{initialize} method specialized to the new class's +metaclass. Such a method could complete override the standard +behaviour, by not calling @code{(next-method)} at all, but more +typically it would perform additional class initialization steps before +and/or after calling @code{(next-method)} for the standard behaviour. + +@node STKlos Compatibility +@subsection STKlos Compatibility + +If the STKlos compatibility module is loaded, @code{define-class} is +overwritten by a STKlos-specific definition; the standard GOOPS +definition of @code{define-class} remains available in +@code{standard-define-class}. + +@deffn syntax standard-define-class name (super @dots{}) slot-definition @dots{} . options +@code{standard-define-class} is equivalent to the standard GOOPS +@code{define-class}. +@end deffn + +@node Creating Instances +@section Creating Instances + +@menu +* Basic Instance Creation:: +* Customizing Instance Creation:: +@end menu + +@node Basic Instance Creation +@subsection Basic Instance Creation + +To create a new instance of any GOOPS class, use the generic function +@code{make} or @code{make-instance}, passing the required class and any +appropriate instance initialization arguments as keyword and value +pairs. Note that @code{make} and @code{make-instances} are aliases for +each other - their behaviour is identical. + +@deffn generic make +@deffnx method make (class ) . initargs +Create and return a new instance of class @var{class}, initialized using +@var{initargs}. + +In theory, @var{initargs} can have any structure that is understood by +whatever methods get applied when the @code{initialize} generic function +is applied to the newly allocated instance. + +In practice, specialized @code{initialize} methods would normally call +@code{(next-method)}, and so eventually the standard GOOPS +@code{initialize} methods are applied. These methods expect +@var{initargs} to be a list with an even number of elements, where +even-numbered elements (counting from zero) are keywords and +odd-numbered elements are the corresponding values. + +GOOPS processes initialization argument keywords automatically for slots +whose definition includes the @code{#:init-keyword} option (@pxref{Slot +Options,, init-keyword}). Other keyword value pairs can only be +processed by an @code{initialize} method that is specialized for the new +instance's class. Any unprocessed keyword value pairs are ignored. +@end deffn + +@deffn generic make-instance +@deffnx method make-instance (class ) . initargs +@code{make-instance} is an alias for @code{make}. +@end deffn + +@node Customizing Instance Creation +@subsection Customizing Instance Creation + +@code{make} itself is a generic function. Hence the @code{make} +invocation itself can be customized in the case where the new instance's +metaclass is more specialized than the default @code{}, by +defining a @code{make} method that is specialized to that metaclass. + +Normally, however, the method for classes with metaclass @code{} +will be applied. This method calls two generic functions: + +@itemize @bullet +@item +(allocate-instance @var{class} . @var{initargs}) + +@item +(initialize @var{instance} . @var{initargs}) +@end itemize + +@code{allocate-instance} allocates storage for and returns the new +instance, uninitialized. You might customize @code{allocate-instance}, +for example, if you wanted to provide a GOOPS wrapper around some other +object programming system. + +To do this, you would create a specialized metaclass, which would act as +the metaclass for all classes and instances from the other system. Then +define an @code{allocate-instance} method, specialized to that +metaclass, which calls a Guile primitive C function, which in turn +allocates the new instance using the interface of the other object +system. + +In this case, for a complete system, you would also need to customize a +number of other generic functions like @code{make} and +@code{initialize}, so that GOOPS knows how to make classes from the +other system, access instance slots, and so on. + +@code{initialize} initializes the instance that is returned by +@code{allocate-instance}. The standard GOOPS methods perform +initializations appropriate to the instance class. + +@itemize @bullet +@item +At the least specialized level, the method for instances of type +@code{} performs internal GOOPS instance initialization, and +initializes the instance's slots according to the slot definitions and +any slot initialization keywords that appear in @var{initargs}. + +@item +The method for instances of type @code{} calls +@code{(next-method)}, then performs the class initializations described +in @ref{Customizing Class Definition}. + +@item +and so on for generic functions, method, operator classes @dots{} +@end itemize + +Similarly, you can customize the initialization of instances of any +application-defined class by defining an @code{initialize} method +specialized to that class. + +Imagine a class whose instances' slots need to be initialized at +instance creation time by querying a database. Although it might be +possible to achieve this a combination of @code{#:init-thunk} keywords +and closures in the slot definitions, it is neater to write an +@code{initialize} method for the class that queries the database once +and initializes all the dependent slot values according to the results. + +@node Accessing Slots +@section Accessing Slots + +The definition of a slot contains at the very least a slot name, and may +also contain various slot options, including getter, setter and/or +accessor functions for the slot. + +It is always possible to access slots by name, using the various +``slot-ref'' and ``slot-set!'' procedures described in the following +subsections. For example, + +@example +(define-class () ;; Define a class with slots + (count #:init-value 0) ;; named "count" and "cache". + (cache #:init-value '()) + @dots{}) + +(define inst (make )) ;; Make an instance of this class. + +(slot-set! inst 'count 5) ;; Set the value of the "count" + ;; slot to 5. + +(slot-set! inst 'cache ;; Modify the value of the + (cons (cons "^it" "It") ;; "cache" slot. + (slot-ref inst 'cache))) +@end example + +If a slot definition includes a getter, setter or accessor function, +these can be used instead of @code{slot-ref} and @code{slot-set!} to +access the slot. + +@example +(define-class () ;; Define a new class whose slots + (count #:setter set-count) ;; use a getter, a setter and + (cache #:accessor cache) ;; an accessor. + (csize #:getter cache-size) + @dots{}) + +(define inst (make )) ;; Make an instance of this class. + +(set-count inst 5) ;; Set the value of the "count" + ;; slot to 5. + +(set! (cache inst) ;; Modify the value of the + (cons (cons "^it" "It") ;; "cache" slot. + (cache inst))) + +(let ((size (cache-size inst))) ;; Get the value of the "csize" + @dots{}) ;; slot. +@end example + +Whichever of these methods is used to access slots, GOOPS always calls +the low-level @dfn{getter} and @dfn{setter} closures for the slot to get +and set its value. These closures make sure that the slot behaves +according to the @code{#:allocation} type that was specified in the slot +definition (@pxref{Slot Options,, allocation}). (For more about these +closures, see @ref{Customizing Class Definition,, compute-get-n-set}.) + +@menu +* Instance Slots:: +* Class Slots:: +* Handling Slot Access Errors:: +@end menu + +@node Instance Slots +@subsection Instance Slots + +Any slot, regardless of its allocation, can be queried, referenced and +set using the following four primitive procedures. + +@deffn {primitive procedure} slot-exists? obj slot-name +Return @code{#t} if @var{obj} has a slot with name @var{slot-name}, +otherwise @code{#f}. +@end deffn + +@deffn {primitive procedure} slot-bound? obj slot-name +Return @code{#t} if the slot named @var{slot-name} in @var{obj} has a +value, otherwise @code{#f}. + +@code{slot-bound?} calls the generic function @code{slot-missing} if +@var{obj} does not have a slot called @var{slot-name} (@pxref{Handling +Slot Access Errors, slot-missing}). +@end deffn + +@deffn {primitive procedure} slot-ref obj slot-name +Return the value of the slot named @var{slot-name} in @var{obj}. + +@code{slot-ref} calls the generic function @code{slot-missing} if +@var{obj} does not have a slot called @var{slot-name} (@pxref{Handling +Slot Access Errors, slot-missing}). + +@code{slot-ref} calls the generic function @code{slot-unbound} if the +named slot in @var{obj} does not have a value (@pxref{Handling Slot +Access Errors, slot-unbound}). +@end deffn + +@deffn {primitive procedure} slot-set! obj slot-name value +Set the value of the slot named @var{slot-name} in @var{obj} to @var{value}. + +@code{slot-set!} calls the generic function @code{slot-missing} if +@var{obj} does not have a slot called @var{slot-name} (@pxref{Handling +Slot Access Errors, slot-missing}). +@end deffn + +GOOPS stores information about slots in class metaobjects. Internally, +all of these procedures work by looking up the slot definition for the +slot named @var{slot-name} in the class metaobject for @code{(class-of +@var{obj})}, and then using the slot definition's ``getter'' and +``setter'' closures to get and set the slot value. + +The next four procedures differ from the previous ones in that they take +the class metaobject as an explicit argument, rather than assuming +@code{(class-of @var{obj})}. Therefore they allow you to apply the +``getter'' and ``setter'' closures of a slot definition in one class to +an instance of a different class. + +[ *fixme* I have no idea why this is useful! Perhaps when a slot in +@code{(class-of @var{obj})} shadows a slot with the same name in one of +its superclasses? There should be an enlightening example here. ] + +@deffn {primitive procedure} slot-exists-using-class? class obj slot-name +Return @code{#t} if the class metaobject @var{class} has a slot +definition for a slot with name @var{slot-name}, otherwise @code{#f}. +@end deffn + +@deffn {primitive procedure} slot-bound-using-class? class obj slot-name +Return @code{#t} if applying @code{slot-ref-using-class} to the same +arguments would call the generic function @code{slot-unbound}, otherwise +@code{#f}. + +@code{slot-bound-using-class?} calls the generic function +@code{slot-missing} if @var{class} does not have a slot definition for a +slot called @var{slot-name} (@pxref{Handling Slot Access Errors, +slot-missing}). +@end deffn + +@deffn {primitive procedure} slot-ref-using-class class obj slot-name +Apply the ``getter'' closure for the slot named @var{slot-name} in +@var{class} to @var{obj}, and return its result. + +@code{slot-ref-using-class} calls the generic function +@code{slot-missing} if @var{class} does not have a slot definition for a +slot called @var{slot-name} (@pxref{Handling Slot Access Errors, +slot-missing}). + +@code{slot-ref-using-class} calls the generic function +@code{slot-unbound} if the application of the ``getter'' closure to +@var{obj} returns an unbound value (@pxref{Handling Slot Access Errors, +slot-unbound}). +@end deffn + +@deffn {primitive procedure} slot-set-using-class! class obj slot-name value +Apply the ``setter'' closure for the slot named @var{slot-name} in +@var{class} to @var{obj} and @var{value}. + +@code{slot-set-using-class!} calls the generic function +@code{slot-missing} if @var{class} does not have a slot definition for a +slot called @var{slot-name} (@pxref{Handling Slot Access Errors, +slot-missing}). +@end deffn + +@node Class Slots +@subsection Class Slots + +Slots whose allocation is per-class rather than per-instance can be +referenced and set without needing to specify any particular instance. + +@deffn procedure class-slot-ref class slot-name +Return the value of the slot named @var{slot-name} in class @var{class}. +The named slot must have @code{#:class} or @code{#:each-subclass} +allocation (@pxref{Slot Options,, allocation}). + +If there is no such slot with @code{#:class} or @code{#:each-subclass} +allocation, @code{class-slot-ref} calls the @code{slot-missing} generic +function with arguments @var{class} and @var{slot-name}. Otherwise, if +the slot value is unbound, @code{class-slot-ref} calls the +@code{slot-missing} generic function, with the same arguments. +@end deffn + +@deffn procedure class-slot-set! class slot-name value +Set the value of the slot named @var{slot-name} in class @var{class} to +@var{value}. The named slot must have @code{#:class} or +@code{#:each-subclass} allocation (@pxref{Slot Options,, allocation}). + +If there is no such slot with @code{#:class} or @code{#:each-subclass} +allocation, @code{class-slot-ref} calls the @code{slot-missing} generic +function with arguments @var{class} and @var{slot-name}. +@end deffn + +@node Handling Slot Access Errors +@subsection Handling Slot Access Errors + +GOOPS calls one of the following generic functions when a ``slot-ref'' +or ``slot-set!'' call specifies a non-existent slot name, or tries to +reference a slot whose value is unbound. + +@deffn generic slot-missing +@deffnx method slot-missing (class ) slot-name +@deffnx method slot-missing (class ) (object ) slot-name +@deffnx method slot-missing (class ) (object ) slot-name value +When an application attempts to reference or set a class or instance +slot by name, and the slot name is invalid for the specified @var{class} +or @var{object}, GOOPS calls the @code{slot-missing} generic function. + +The default methods all call @code{goops-error} with an appropriate +message. +@end deffn + +@deffn generic slot-unbound +@deffnx method slot-unbound (object ) +@deffnx method slot-unbound (class ) slot-name +@deffnx method slot-unbound (class ) (object ) slot-name +When an application attempts to reference a class or instance slot, and +the slot's value is unbound, GOOPS calls the @code{slot-unbound} generic +function. + +The default methods all call @code{goops-error} with an appropriate +message. +@end deffn + +@node Creating Generic Functions +@section Creating Generic Functions + +A generic function is a collection of methods, with rules for +determining which of the methods should be applied for any given +invocation of the generic function. + +GOOPS represents generic functions as metaobjects of the class +@code{} (or one of its subclasses). + +@menu +* Basic Generic Function Creation:: +* Generic Function Internals:: +* Extending Guiles Primitives:: +@end menu + +@node Basic Generic Function Creation +@subsection Basic Generic Function Creation + +The following forms may be used to bind a variable to a generic +function. Depending on that variable's pre-existing value, the generic +function may be created empty - with no methods - or it may contain +methods that are inferred from the pre-existing value. + +It is not, in general, necessary to use @code{define-generic} or +@code{define-accessor} before defining methods for the generic function +using @code{define-method}, since @code{define-method} will +automatically interpolate a @code{define-generic} call, or upgrade an +existing generic to an accessor, if that is implied by the +@code{define-method} call. Note in particular that, +if the specified variable already has a @emph{generic function} value, +@code{define-generic} and @code{define-accessor} will @emph{discard} it! +Obviously it is application-dependent whether this is desirable or not. + +If, for example, you wanted to extend @code{+} for a class representing +a new numerical type, you probably want to inherit any existing methods +for @code{+} and so should not use @code{define-generic}. If, on the +other hand, you do not want to risk inheriting methods whose behaviour +might surprise you, you can use @code{define-generic} or +@code{define-accessor} to wipe the slate clean. + +@deffn syntax define-generic symbol +Create a generic function with name @var{symbol} and bind it to the +variable @var{symbol}. + +If the variable @var{symbol} was previously bound to a Scheme procedure +(or procedure-with-setter), the old procedure (and setter) is +incorporated into the new generic function as its default procedure (and +setter). Any other previous value that was bound to @var{symbol}, +including an existing generic function, is overwritten by the new +generic function. +@end deffn + +@deffn syntax define-accessor symbol +Create an accessor with name @var{symbol} and bind it to the variable +@var{symbol}. + +If the variable @var{symbol} was previously bound to a Scheme procedure +(or procedure-with-setter), the old procedure (and setter) is +incorporated into the new accessor as its default procedure (and +setter). Any other previous value that was bound to @var{symbol}, +including an existing generic function or accessor, is overwritten by +the new definition. +@end deffn + +@node Generic Function Internals +@subsection Generic Function Internals + +@code{define-generic} calls @code{ensure-generic} to upgrade a +pre-existing procedure value, or @code{make} with metaclass +@code{} to create a new generic function. + +@code{define-accessor} calls @code{ensure-accessor} to upgrade a +pre-existing procedure value, or @code{make-accessor} to create a new +accessor. + +@deffn procedure ensure-generic old-definition [name] +Return a generic function with name @var{name}, if possible by using or +upgrading @var{old-definition}. If unspecified, @var{name} defaults to +@code{#f}. + +If @var{old-definition} is already a generic function, it is returned +unchanged. + +If @var{old-definition} is a Scheme procedure or procedure-with-setter, +@code{ensure-generic} returns a new generic function that uses +@var{old-definition} for its default procedure and setter. + +Otherwise @code{ensure-generic} returns a new generic function with no +defaults and no methods. +@end deffn + +@deffn procedure make-generic [name] +Return a new generic function with name @code{(car @var{name})}. If +unspecified, @var{name} defaults to @code{#f}. +@end deffn + +@code{ensure-generic} calls @code{make} with metaclasses +@code{} and @code{}, depending on the +previous value of the variable that it is trying to upgrade. + +@code{make-generic} is a simple wrapper for @code{make} with metaclass +@code{}. + +@deffn procedure ensure-accessor proc [name] +Return an accessor with name @var{name}, if possible by using or +upgrading @var{proc}. If unspecified, @var{name} defaults to @code{#f}. + +If @var{proc} is already an accessor, it is returned unchanged. + +If @var{proc} is a Scheme procedure, procedure-with-setter or generic +function, @code{ensure-accessor} returns an accessor that reuses the +reusable elements of @var{proc}. + +Otherwise @code{ensure-accessor} returns a new accessor with no defaults +and no methods. +@end deffn + +@deffn procedure make-accessor [name] +Return a new accessor with name @code{(car @var{name})}. If +unspecified, @var{name} defaults to @code{#f}. +@end deffn + +@code{ensure-accessor} calls @code{make} with +metaclass @code{}, as well as calls to +@code{ensure-generic}, @code{make-accessor} and (tail recursively) +@code{ensure-accessor}. + +@code{make-accessor} calls @code{make} twice, first +with metaclass @code{} to create a generic function for the +setter, then with metaclass @code{} to create the +accessor, passing the setter generic function as the value of the +@code{#:setter} keyword. + +@node Extending Guiles Primitives +@subsection Extending Guile's Primitives + +When GOOPS is loaded, many of Guile's primitive procedures can be +extended by giving them a generic function definition that operates +in conjunction with their normal C-coded implementation. For +primitives that are extended in this way, the result from the user- +or application-level point of view is that the extended primitive +behaves exactly like a generic function with the C-coded implementation +as its default method. + +The @code{generic-capability?} predicate should be used to determine +whether a particular primitive is extensible in this way. + +@deffn {primitive procedure} generic-capability? primitive +Return @code{#t} if @var{primitive} can be extended by giving it a +generic function definition, otherwise @code{#f}. +@end deffn + +Even when a primitive procedure is extensible like this, its generic +function definition is not created until it is needed by a call to +@code{define-method}, or until the application explicitly requests it +by calling @code{enable-primitive-generic!}. + +@deffn {primitive procedure} enable-primitive-generic! primitive +Force the creation of a generic function definition for +@var{primitive}. +@end deffn + +Once the generic function definition for a primitive has been created, +it can be retrieved using @code{primitive-generic-generic}. + +@deffn {primitive procedure} primitive-generic-generic primitive +Return the generic function definition of @var{primitive}. + +@code{primitive-generic-generic} raises an error if @var{primitive} +is not a primitive with generic capability, or if its generic capability +has not yet been enabled, whether implicitly (by @code{define-method}) +or explicitly (by @code{enable-primitive-generic!}). +@end deffn + +Note that the distinction between, on the one hand, primitives with +additional generic function definitions and, on the other hand, generic +functions with a default method, may disappear when GOOPS is fully +integrated into the core of Guile. Consequently, the +procedures described in this section may disappear as well. + +@node Adding Methods to Generic Functions +@section Adding Methods to Generic Functions + +@menu +* Basic Method Definition:: +* Method Definition Internals:: +@end menu + +@node Basic Method Definition +@subsection Basic Method Definition + +To add a method to a generic function, use the @code{define-method} form. + +@deffn syntax define-method (generic parameter @dots{}) . body +Define a method for the generic function or accessor @var{generic} with +parameters @var{parameter}s and body @var{body}. + +@var{generic} is a generic function. If @var{generic} is a variable +which is not yet bound to a generic function object, the expansion of +@code{define-method} will include a call to @code{define-generic}. If +@var{generic} is @code{(setter @var{generic-with-setter})}, where +@var{generic-with-setter} is a variable which is not yet bound to a +generic-with-setter object, the expansion will include a call to +@code{define-accessor}. + +Each @var{parameter} must be either a symbol or a two-element list +@code{(@var{symbol} @var{class})}. The symbols refer to variables in +the @var{body} that will be bound to the parameters supplied by the +caller when calling this method. The @var{class}es, if present, +specify the possible combinations of parameters to which this method +can be applied. + +@var{body} is the body of the method definition. +@end deffn + +@code{define-method} expressions look a little like normal Scheme +procedure definitions of the form + +@example +(define (name formals @dots{}) . body) +@end example + +The most important difference is that each formal parameter, apart from the +possible ``rest'' argument, can be qualified by a class name: +@code{@var{formal}} becomes @code{(@var{formal} @var{class})}. The +meaning of this qualification is that the method being defined +will only be applicable in a particular generic function invocation if +the corresponding argument is an instance of @code{@var{class}} (or one of +its subclasses). If more than one of the formal parameters is qualified +in this way, then the method will only be applicable if each of the +corresponding arguments is an instance of its respective qualifying class. + +Note that unqualified formal parameters act as though they are qualified +by the class @code{}, which GOOPS uses to mean the superclass of +all valid Scheme types, including both primitive types and GOOPS classes. + +For example, if a generic function method is defined with +@var{parameter}s @code{((s1 ) (n ))}, that method is +only applicable to invocations of its generic function that have two +parameters where the first parameter is an instance of the +@code{} class and the second parameter is a number. + +If a generic function is invoked with a combination of parameters for which +there is no applicable method, GOOPS raises an error. For more about +invocation error handling, and generic function invocation in general, +see @ref{Invoking Generic Functions}. + +@node Method Definition Internals +@subsection Method Definition Internals + +@code{define-method} + +@itemize @bullet +@item +checks the form of the first parameter, and applies the following steps +to the accessor's setter if it has the @code{(setter @dots{})} form + +@item +interpolates a call to @code{define-generic} or @code{define-accessor} +if a generic function is not already defined with the supplied name + +@item +calls @code{method} with the @var{parameter}s and @var{body}, to make a +new method instance + +@item +calls @code{add-method!} to add this method to the relevant generic +function. +@end itemize + +@deffn syntax method (parameter @dots{}) . body +Make a method whose specializers are defined by the classes in +@var{parameter}s and whose procedure definition is constructed from the +@var{parameter} symbols and @var{body} forms. + +The @var{parameter} and @var{body} parameters should be as for +@code{define-method} (@pxref{Basic Method Definition,, define-method}). +@end deffn + +@code{method} + +@itemize @bullet +@item +extracts formals and specializing classes from the @var{parameter}s, +defaulting the class for unspecialized parameters to @code{} + +@item +creates a closure using the formals and the @var{body} forms + +@item +calls @code{make} with metaclass @code{} and the specializers +and closure using the @code{#:specializers} and @code{#:procedure} +keywords. +@end itemize + +@deffn procedure make-method specializers procedure +Make a method using @var{specializers} and @var{procedure}. + +@var{specializers} should be a list of classes that specifies the +parameter combinations to which this method will be applicable. + +@var{procedure} should be the closure that will applied to the generic +function parameters when this method is invoked. +@end deffn + +@code{make-method} is a simple wrapper around @code{make} with metaclass +@code{}. + +@deffn generic add-method! target method +Generic function for adding method @var{method} to @var{target}. +@end deffn + +@deffn method add-method! (generic ) (method ) +Add method @var{method} to the generic function @var{generic}. +@end deffn + +@deffn method add-method! (proc ) (method ) +If @var{proc} is a procedure with generic capability (@pxref{Extending +Guiles Primitives,, generic-capability?}), upgrade it to a +primitive generic and add @var{method} to its generic function +definition. +@end deffn + +@deffn method add-method! (pg ) (method ) +Add method @var{method} to the generic function definition of @var{pg}. + +Implementation: @code{(add-method! (primitive-generic-generic pg) method)}. +@end deffn + +@deffn method add-method! (whatever ) (method ) +Raise an error indicating that @var{whatever} is not a valid generic +function. +@end deffn + +@node Invoking Generic Functions +@section Invoking Generic Functions + +When a variable with a generic function definition appears as the first +element of a list that is being evaluated, the Guile evaluator tries +to apply the generic function to the arguments obtained by evaluating +the remaining elements of the list. [ *fixme* How do I put this in a +more Schemely and less Lispy way? ] + +Usually a generic function contains several method definitions, with +varying degrees of formal parameter specialization (@pxref{Basic +Method Definition,, define-method}). So it is necessary to sort these +methods by specificity with respect to the supplied arguments, and then +apply the most specific method definition. Less specific methods +may be applied subsequently if a method that is being applied calls +@code{next-method}. + +@menu +* Determining Which Methods to Apply:: +* Handling Invocation Errors:: +@end menu + +@node Determining Which Methods to Apply +@subsection Determining Which Methods to Apply + +[ *fixme* Sorry - this is the area of GOOPS that I understand least of +all, so I'm afraid I have to pass on this section. Would some other +kind person consider filling it in? ] + +@deffn generic apply-generic +@deffnx method apply-generic (gf ) args +@end deffn + +@deffn generic compute-applicable-methods +@deffnx method compute-applicable-methods (gf ) args +@end deffn + +@deffn generic sort-applicable-methods +@deffnx method sort-applicable-methods (gf ) methods args +@end deffn + +@deffn generic method-more-specific? +@deffnx method method-more-specific? (m1 ) (m2 ) args +@end deffn + +@deffn generic apply-method +@deffnx method apply-method (gf ) methods build-next args +@end deffn + +@deffn generic apply-methods +@deffnx method apply-methods (gf ) (l ) args +@end deffn + +@node Handling Invocation Errors +@subsection Handling Invocation Errors + +@deffn generic no-method +@deffnx method no-method (gf ) args +When an application invokes a generic function, and no methods at all +have been defined for that generic function, GOOPS calls the +@code{no-method} generic function. The default method calls +@code{goops-error} with an appropriate message. +@end deffn + +@deffn generic no-applicable-method +@deffnx method no-applicable-method (gf ) args +When an application applies a generic function to a set of arguments, +and no methods have been defined for those argument types, GOOPS calls +the @code{no-applicable-method} generic function. The default method +calls @code{goops-error} with an appropriate message. +@end deffn + +@deffn generic no-next-method +@deffnx method no-next-method (gf ) args +When a generic function method calls @code{(next-method)} to invoke the +next less specialized method for that generic function, and no less +specialized methods have been defined for the current generic function +arguments, GOOPS calls the @code{no-next-method} generic function. The +default method calls @code{goops-error} with an appropriate message. +@end deffn + +@node Redefining a Class +@section Redefining a Class + +Suppose that a class @code{} is defined using @code{define-class} +(@pxref{Basic Class Definition,, define-class}), with slots that have +accessor functions, and that an application has created several instances +of @code{} using @code{make} (@pxref{Basic Instance Creation,, +make}). What then happens if @code{} is redefined by calling +@code{define-class} again? + +@menu +* Default Class Redefinition Behaviour:: +* Customizing Class Redefinition:: +@end menu + +@node Default Class Redefinition Behaviour +@subsection Default Class Redefinition Behaviour + +GOOPS' default answer to this question is as follows. + +@itemize @bullet +@item +All existing direct instances of @code{} are converted to be +instances of the new class. This is achieved by preserving the values +of slots that exist in both the old and new definitions, and initializing the +values of new slots in the usual way (@pxref{Basic Instance Creation,, +make}). + +@item +All existing subclasses of @code{} are redefined, as though +the @code{define-class} expressions that defined them were re-evaluated +following the redefinition of @code{}, and the class +redefinition process described here is applied recursively to the +redefined subclasses. + +@item +Once all of its instances and subclasses have been updated, the class +metaobject previously bound to the variable @code{} is no +longer needed and so can be allowed to be garbage collected. +@end itemize + +To keep things tidy, GOOPS also needs to do a little housekeeping on +methods that are associated with the redefined class. + +@itemize @bullet +@item +Slot accessor methods for slots in the old definition should be removed +from their generic functions. They will be replaced by accessor methods +for the slots of the new class definition. + +@item +Any generic function method that uses the old @code{} metaobject +as one of its formal parameter specializers must be updated to refer to +the new @code{} metaobject. (Whenever a new generic function +method is defined, @code{define-method} adds the method to a list stored +in the class metaobject for each class used as a formal parameter +specializer, so it is easy to identify all the methods that must be +updated when a class is redefined.) +@end itemize + +If this class redefinition strategy strikes you as rather counter-intuitive, +bear in mind that it is derived from similar behaviour in other object +systems such as CLOS, and that experience in those systems has shown it to be +very useful in practice. + +Also bear in mind that, like most of GOOPS' default behaviour, it can +be customized@dots{} + +@node Customizing Class Redefinition +@subsection Customizing Class Redefinition + +When @code{define-class} notices that a class is being redefined, +it constructs the new class metaobject as usual, and then invokes the +@code{class-redefinition} generic function with the old and new classes +as arguments. Therefore, if the old or new classes have metaclasses +other than the default @code{}, class redefinition behaviour can +be customized by defining a @code{class-redefinition} method that is +specialized for the relevant metaclasses. + +@deffn generic class-redefinition +Handle the class redefinition from @var{old-class} to @var{new-class}, +and return the new class metaobject that should be bound to the +variable specified by @code{define-class}'s first argument. +@end deffn + +@deffn method class-redefinition (old-class ) (new-class ) +Implements GOOPS' default class redefinition behaviour, as described in +@ref{Default Class Redefinition Behaviour}. Returns the metaobject +for the new class definition. +@end deffn + +An alternative class redefinition strategy could be to leave all +existing instances as instances of the old class, but accepting that the +old class is now ``nameless'', since its name has been taken over by the +new definition. In this strategy, any existing subclasses could also +be left as they are, on the understanding that they inherit from a nameless +superclass. + +This strategy is easily implemented in GOOPS, by defining a new metaclass, +that will be used as the metaclass for all classes to which the strategy +should apply, and then defining a @code{class-redefinition} method that +is specialized for this metaclass: + +@example +(define-class ()) + +(define-method (class-redefinition (old ) (new )) + new) +@end example + +When customization can be as easy as this, aren't you glad that GOOPS +implements the far more difficult strategy as its default! + +Finally, note that, if @code{class-redefinition} itself is not customized, +the default @code{class-redefinition} method invokes three further +generic functions that could be individually customized: + +@itemize @bullet +@item +(remove-class-accessors! @var{old-class}) + +@item +(update-direct-method! @var{method} @var{old-class} @var{new-class}) + +@item +(update-direct-subclass! @var{subclass} @var{old-class} @var{new-class}) +@end itemize + +and the default methods for these generic functions invoke further +generic functions, and so on@dots{} The detailed protocol for all of these +is described in @ref{MOP Specification}. + +@node Changing the Class of an Instance +@section Changing the Class of an Instance + +You can change the class of an existing instance by invoking the +generic function @code{change-class} with two arguments: the instance +and the new class. + +@deffn generic change-class +@end deffn + +The default method for @code{change-class} decides how to implement the +change of class by looking at the slot definitions for the instance's +existing class and for the new class. If the new class has slots with +the same name as slots in the existing class, the values for those slots +are preserved. Slots that are present only in the existing class are +discarded. Slots that are present only in the new class are initialized +using the corresponding slot definition's init function (@pxref{Classes,, +slot-init-function}). + +@deffn {method} change-class (obj ) (new ) +Modify instance @var{obj} to make it an instance of class @var{new}. + +The value of each of @var{obj}'s slots is preserved only if a similarly named +slot exists in @var{new}; any other slot values are discarded. + +The slots in @var{new} that do not correspond to any of @var{obj}'s +pre-existing slots are initialized according to @var{new}'s slot definitions' +init functions. +@end deffn + +Customized change of class behaviour can be implemented by defining +@code{change-class} methods that are specialized either by the class +of the instances to be modified or by the metaclass of the new class. + +When a class is redefined (@pxref{Redefining a Class}), and the default +class redefinition behaviour is not overridden, GOOPS (eventually) +invokes the @code{change-class} generic function for each existing +instance of the redefined class. + +@node Introspection +@section Introspection + +@dfn{Introspection}, also known as @dfn{reflection}, is the name given +to the ability to obtain information dynamically about GOOPS metaobjects. +It is perhaps best illustrated by considering an object oriented language +that does not provide any introspection, namely C++. + +Nothing in C++ allows a running program to obtain answers to the following +types of question: + +@itemize @bullet +@item +What are the data members of this object or class? + +@item +What classes does this class inherit from? + +@item +Is this method call virtual or non-virtual? + +@item +If I invoke @code{Employee::adjustHoliday()}, what class contains the +@code{adjustHoliday()} method that will be applied? +@end itemize + +In C++, answers to such questions can only be determined by looking at +the source code, if you have access to it. GOOPS, on the other hand, +includes procedures that allow answers to these questions --- or their +GOOPS equivalents --- to be obtained dynamically, at run time. + +@menu +* Classes:: +* Slots:: +* Instances:: +* Generic Functions:: +* Generic Function Methods:: +@end menu + +@node Classes +@subsection Classes + +@deffn {primitive procedure} class-name class +Return the name of class @var{class}. +This is the value of the @var{class} metaobject's @code{name} slot. +@end deffn + +@deffn {primitive procedure} class-direct-supers class +Return a list containing the direct superclasses of @var{class}. +This is the value of the @var{class} metaobject's +@code{direct-supers} slot. +@end deffn + +@deffn {primitive procedure} class-direct-slots class +Return a list containing the slot definitions of the direct slots of +@var{class}. +This is the value of the @var{class} metaobject's @code{direct-slots} +slot. +@end deffn + +@deffn {primitive procedure} class-direct-subclasses class +Return a list containing the direct subclasses of @var{class}. +This is the value of the @var{class} metaobject's +@code{direct-subclasses} slot. +@end deffn + +@deffn {primitive procedure} class-direct-methods class +Return a list of all the generic function methods that use @var{class} +as a formal parameter specializer. +This is the value of the @var{class} metaobject's @code{direct-methods} +slot. +@end deffn + +@deffn {primitive procedure} class-precedence-list class +Return the class precedence list for class @var{class} (@pxref{Class +precedence list}). +This is the value of the @var{class} metaobject's @code{cpl} slot. +@end deffn + +@deffn {primitive procedure} class-slots class +Return a list containing the slot definitions for all @var{class}'s slots, +including any slots that are inherited from superclasses. +This is the value of the @var{class} metaobject's @code{slots} slot. +@end deffn + +@deffn {primitive procedure} class-environment class +Return the value of @var{class}'s @code{environment} slot. +[ *fixme* I don't know what this value is used for. ] +@end deffn + +@deffn procedure class-subclasses class +Return a list of all subclasses of @var{class}. +@end deffn + +@deffn procedure class-methods class +Return a list of all methods that use @var{class} or a subclass of +@var{class} as one of its formal parameter specializers. +@end deffn + +@node Slots +@subsection Slots + +@deffn procedure class-slot-definition class slot-name +Return the slot definition for the slot named @var{slot-name} in class +@var{class}. @var{slot-name} should be a symbol. +@end deffn + +@deffn procedure slot-definition-name slot-def +Extract and return the slot name from @var{slot-def}. +@end deffn + +@deffn procedure slot-definition-options slot-def +Extract and return the slot options from @var{slot-def}. +@end deffn + +@deffn procedure slot-definition-allocation slot-def +Extract and return the slot allocation option from @var{slot-def}. This +is the value of the @code{#:allocation} keyword (@pxref{Slot Options,, +allocation}), or @code{#:instance} if the @code{#:allocation} keyword is +absent. +@end deffn + +@deffn procedure slot-definition-getter slot-def +Extract and return the slot getter option from @var{slot-def}. This is +the value of the @code{#:getter} keyword (@pxref{Slot Options,, +getter}), or @code{#f} if the @code{#:getter} keyword is absent. +@end deffn + +@deffn procedure slot-definition-setter slot-def +Extract and return the slot setter option from @var{slot-def}. This is +the value of the @code{#:setter} keyword (@pxref{Slot Options,, +setter}), or @code{#f} if the @code{#:setter} keyword is absent. +@end deffn + +@deffn procedure slot-definition-accessor slot-def +Extract and return the slot accessor option from @var{slot-def}. This +is the value of the @code{#:accessor} keyword (@pxref{Slot Options,, +accessor}), or @code{#f} if the @code{#:accessor} keyword is absent. +@end deffn + +@deffn procedure slot-definition-init-value slot-def +Extract and return the slot init-value option from @var{slot-def}. This +is the value of the @code{#:init-value} keyword (@pxref{Slot Options,, +init-value}), or the unbound value if the @code{#:init-value} keyword is +absent. +@end deffn + +@deffn procedure slot-definition-init-form slot-def +Extract and return the slot init-form option from @var{slot-def}. This +is the value of the @code{#:init-form} keyword (@pxref{Slot Options,, +init-form}), or the unbound value if the @code{#:init-form} keyword is +absent. +@end deffn + +@deffn procedure slot-definition-init-thunk slot-def +Extract and return the slot init-thunk option from @var{slot-def}. This +is the value of the @code{#:init-thunk} keyword (@pxref{Slot Options,, +init-thunk}), or @code{#f} if the @code{#:init-thunk} keyword is absent. +@end deffn + +@deffn procedure slot-definition-init-keyword slot-def +Extract and return the slot init-keyword option from @var{slot-def}. +This is the value of the @code{#:init-keyword} keyword (@pxref{Slot +Options,, init-keyword}), or @code{#f} if the @code{#:init-keyword} +keyword is absent. +@end deffn + +@deffn procedure slot-init-function class slot-name +Return the initialization function for the slot named @var{slot-name} in +class @var{class}. @var{slot-name} should be a symbol. + +The returned initialization function incorporates the effects of the +standard @code{#:init-thunk}, @code{#:init-form} and @code{#:init-value} +slot options. These initializations can be overridden by the +@code{#:init-keyword} slot option or by a specialized @code{initialize} +method, so, in general, the function returned by +@code{slot-init-function} may be irrelevant. For a fuller discussion, +see @ref{Slot Options,, init-value}. +@end deffn + +@node Instances +@subsection Instances + +@deffn {primitive procedure} class-of value +Return the GOOPS class of any Scheme @var{value}. +@end deffn + +@deffn {primitive procedure} instance? object +Return @code{#t} if @var{object} is any GOOPS instance, otherwise +@code{#f}. +@end deffn + +@deffn procedure is-a? object class +Return @code{#t} if @var{object} is an instance of @var{class} or one of +its subclasses. +@end deffn + +Implementation notes: @code{is-a?} uses @code{class-of} and +@code{class-precedence-list} to obtain the class precedence list for +@var{object}. + +@node Generic Functions +@subsection Generic Functions + +@deffn {primitive procedure} generic-function-name gf +Return the name of generic function @var{gf}. +@end deffn + +@deffn {primitive procedure} generic-function-methods gf +Return a list of the methods of generic function @var{gf}. +This is the value of the @var{gf} metaobject's @code{methods} slot. +@end deffn + +@node Generic Function Methods +@subsection Generic Function Methods + +@deffn {primitive procedure} method-generic-function method +Return the generic function that @var{method} belongs to. +This is the value of the @var{method} metaobject's +@code{generic-function} slot. +@end deffn + +@deffn {primitive procedure} method-specializers method +Return a list of @var{method}'s formal parameter specializers . +This is the value of the @var{method} metaobject's +@code{specializers} slot. +@end deffn + +@deffn {primitive procedure} method-procedure method +Return the procedure that implements @var{method}. +This is the value of the @var{method} metaobject's +@code{procedure} slot. +@end deffn + +@deffn generic method-source +@deffnx method method-source (m ) +Return an expression that prints to show the definition of method +@var{m}. + +@example +(define-generic cube) + +(define-method (cube (n )) + (* n n n)) + +(map method-source (generic-function-methods cube)) +@result{} +((method ((n )) (* n n n))) +@end example +@end deffn + +@node Miscellaneous Functions +@section Miscellaneous Functions + +@menu +* Administrative Functions:: +* Error Handling:: +* Object Comparisons:: +* Cloning Objects:: +* Write and Display:: +@end menu + +@node Administrative Functions +@subsection Administration Functions + +This section describes administrative, non-technical GOOPS functions. + +@deffn primitive goops-version +Return the current GOOPS version as a string, for example ``0.2''. +@end deffn + +@node Error Handling +@subsection Error Handling + +The procedure @code{goops-error} is called to raise an appropriate error +by the default methods of the following generic functions: + +@itemize @bullet +@item +@code{slot-missing} (@pxref{Handling Slot Access Errors,, slot-missing}) + +@item +@code{slot-unbound} (@pxref{Handling Slot Access Errors,, slot-unbound}) + +@item +@code{no-method} (@pxref{Handling Invocation Errors,, no-method}) + +@item +@code{no-applicable-method} (@pxref{Handling Invocation Errors,, +no-applicable-method}) + +@item +@code{no-next-method} (@pxref{Handling Invocation Errors,, +no-next-method}) +@end itemize + +If you customize these functions for particular classes or metaclasses, +you may still want to use @code{goops-error} to signal any error +conditions that you detect. + +@deffn procedure goops-error format-string . args +Raise an error with key @code{goops-error} and error message constructed +from @var{format-string} and @var{args}. Error message formatting is +as done by @code{scm-error}. +@end deffn + +@node Object Comparisons +@subsection Object Comparisons + +@deffn generic object-eqv? +@deffnx method object-eqv? ((x ) (y )) +@deffnx generic object-equal? +@deffnx method object-equal? ((x ) (y )) +Generic functions and default (unspecialized) methods for comparing two +GOOPS objects. + +The default methods always return @code{#f}. Application class authors +may wish to define specialized methods for @code{object-eqv?} and +@code{object-equal?} that compare instances of the same class for +equality in whatever sense is useful to the application. +@end deffn + +@node Cloning Objects +@subsection Cloning Objects + +@deffn generic shallow-clone +@deffnx method shallow-clone (self ) +Return a ``shallow'' clone of @var{self}. The default method makes a +shallow clone by allocating a new instance and copying slot values from +self to the new instance. Each slot value is copied either as an +immediate value or by reference. +@end deffn + +@deffn generic deep-clone +@deffnx method deep-clone (self ) +Return a ``deep'' clone of @var{self}. The default method makes a deep +clone by allocating a new instance and copying or cloning slot values +from self to the new instance. If a slot value is an instance +(satisfies @code{instance?}), it is cloned by calling @code{deep-clone} +on that value. Other slot values are copied either as immediate values +or by reference. +@end deffn + +@node Write and Display +@subsection Write and Display + +@deffn {primitive generic} write object port +@deffnx {primitive generic} display object port +When GOOPS is loaded, @code{write} and @code{display} become generic +functions with special methods for printing + +@itemize @bullet +@item +objects - instances of the class @code{} + +@item +foreign objects - instances of the class @code{} + +@item +classes - instances of the class @code{} + +@item +generic functions - instances of the class @code{} + +@item +methods - instances of the class @code{}. +@end itemize + +@code{write} and @code{display} print non-GOOPS values in the same way +as the Guile primitive @code{write} and @code{display} functions. +@end deffn + +@node MOP Specification, Tutorial, Reference Manual, Top +@chapter MOP Specification + +For an introduction to metaobjects and the metaobject protocol, +see @ref{Metaobjects and the Metaobject Protocol}. + +The aim of the MOP specification in this chapter is to specify all the +customizable generic function invocations that can be made by the standard +GOOPS syntax, procedures and methods, and to explain the protocol for +customizing such invocations. + +A generic function invocation is customizable if the types of the arguments +to which it is applied are not all determined by the lexical context in +which the invocation appears. For example, + +@itemize @bullet +@item +the @code{(initialize @var{instance} @var{initargs})} invocation in the +default @code{make-instance} method is customizable, because the type of the +@code{@var{instance}} argument is determined by the class that was passed to +@code{make-instance}. + +@item +the @code{(make #:name ',name)} invocation in @code{define-generic} +is not customizable, because all of its arguments have lexically determined +types. +@end itemize + +When using this rule to decide whether a given generic function invocation +is customizable, we ignore arguments that are expected to be handled in +method definitions as a single ``rest'' list argument. + +For each customizable generic function invocation, the @dfn{invocation +protocol} is explained by specifying + +@itemize @bullet +@item +what, conceptually, the applied method is intended to do + +@item +what assumptions, if any, the caller makes about the applied method's side +effects + +@item +what the caller expects to get as the applied method's return value. +@end itemize + +@menu +* Class Definition:: +* Instance Creation:: +* Class Redefinition:: +* Method Definition:: +* Generic Function Invocation:: +@end menu + +@node Class Definition +@section Class Definition + +@code{define-class} (syntax) + +@itemize @bullet +@item +@code{class} (syntax) + +@itemize @bullet +@item +@code{make-class} (procedure) + +@itemize @bullet +@item +@code{make @var{metaclass} @dots{}} (generic) + +@var{metaclass} is the metaclass of the class being defined, either +taken from the @code{#:metaclass} class option or computed by +@code{ensure-metaclass}. The applied method must create and return the +fully initialized class metaobject for the new class definition. +@end itemize + +@end itemize + +@item +@code{class-redefinition @var{old-class} @var{new-class}} (generic) + +@code{define-class} calls @code{class-redefinition} if the variable +specified by its first argument already held a GOOPS class definition. +@var{old-class} and @var{new-class} are the old and new class metaobjects. +The applied method should perform whatever is necessary to handle the +redefinition, and should return the class metaobject that is to be bound +to @code{define-class}'s variable. The default class redefinition +protocol is described in @ref{Class Redefinition}. +@end itemize + +The @code{(make @var{metaclass} @dots{})} invocation above will create +an class metaobject with metaclass @var{metaclass}. By default, this +metaobject will be initialized by the @code{initialize} method that is +specialized for instances of type @code{}. + +@code{initialize @var{initargs}} (method) + +@itemize @bullet +@item +@code{compute-cpl @var{class}} (generic) + +The applied method should compute and return the class precedence list +for @var{class} as a list of class metaobjects. When @code{compute-cpl} +is called, the following @var{class} metaobject slots have all been +initialized: @code{name}, @code{direct-supers}, @code{direct-slots}, +@code{direct-subclasses} (empty), @code{direct-methods}. The value +returned by @code{compute-cpl} will be stored in the @code{cpl} slot. + +@item +@code{compute-slots @var{class}} (generic) + +The applied method should compute and return the slots (union of direct +and inherited) for @var{class} as a list of slot definitions. When +@code{compute-slots} is called, all the @var{class} metaobject slots +mentioned for @code{compute-cpl} have been initialized, plus the +following: @code{cpl}, @code{redefined} (@code{#f}), @code{environment}. +The value returned by @code{compute-slots} will be stored in the +@code{slots} slot. + +@item +@code{compute-get-n-set @var{class} @var{slot-def}} (generic) + +@code{initialize} calls @code{compute-get-n-set} for each slot computed +by @code{compute-slots}. The applied method should compute and return a +pair of closures that, respectively, get and set the value of the specified +slot. The get closure should have arity 1 and expect a single argument +that is the instance whose slot value is to be retrieved. The set closure +should have arity 2 and expect two arguments, where the first argument is +the instance whose slot value is to be set and the second argument is the +new value for that slot. The closures should be returned in a two element +list: @code{(list @var{get} @var{set})}. + +The closures returned by @code{compute-get-n-set} are stored as part of +the value of the @var{class} metaobject's @code{getters-n-setters} slot. +Specifically, the value of this slot is a list with the same number of +elements as there are slots in the class, and each element looks either like + +@example +@code{(@var{slot-name-symbol} @var{init-function} . @var{index})} +@end example + +or like + +@example +@code{(@var{slot-name-symbol} @var{init-function} @var{get} @var{set})} +@end example + +Where the get and set closures are replaced by @var{index}, the slot is +an instance slot and @var{index} is the slot's index in the underlying +structure: GOOPS knows how to get and set the value of such slots and so +does not need specially constructed get and set closures. Otherwise, +@var{get} and @var{set} are the closures returned by @code{compute-get-n-set}. + +The structure of the @code{getters-n-setters} slot value is important when +understanding the next customizable generic functions that @code{initialize} +calls@dots{} + +@item +@code{compute-getter-method @var{class} @var{gns}} (generic) + +@code{initialize} calls @code{compute-getter-method} for each of the class's +slots (as determined by @code{compute-slots}) that includes a +@code{#:getter} or @code{#:accessor} slot option. @var{gns} is the +element of the @var{class} metaobject's @code{getters-n-setters} slot that +specifies how the slot in question is referenced and set, as described +above under @code{compute-get-n-set}. The applied method should create +and return a method that is specialized for instances of type @var{class} +and uses the get closure to retrieve the slot's value. [ *fixme Need +to insert something here about checking that the value is not unbound. ] +@code{initialize} uses @code{add-method!} to add the returned method to +the generic function named by the slot definition's @code{#:getter} or +@code{#:accessor} option. + +@item +@code{compute-setter-method @var{class} @var{gns}} (generic) + +@code{compute-setter-method} is invoked with the same arguments as +@code{compute-getter-method}, for each of the class's slots that includes +a @code{#:setter} or @code{#:accessor} slot option. The applied method +should create and return a method that is specialized for instances of +type @var{class} and uses the set closure to set the slot's value. +@code{initialize} then uses @code{add-method!} to add the returned method +to the generic function named by the slot definition's @code{#:setter} +or @code{#:accessor} option. +@end itemize + +@node Instance Creation +@section Instance Creation + +@code{make . @var{initargs}} (method) + +@itemize @bullet +@item +@code{allocate-instance @var{class} @var{initargs}} (generic) + +The applied @code{allocate-instance} method should allocate storage for +a new instance of class @var{class} and return the uninitialized instance. + +@item +@code{initialize @var{instance} @var{initargs}} (generic) + +@var{instance} is the uninitialized instance returned by +@code{allocate-instance}. The applied method should initialize the new +instance in whatever sense is appropriate for its class. The method's +return value is ignored. +@end itemize + +@node Class Redefinition +@section Class Redefinition + +The default @code{class-redefinition} method, specialized for classes +with the default metaclass @code{}, has the following internal +protocol. + +[ *fixme* I'm not sure that I understand this sufficiently to explain +it. Also, the internals of the default class redefinition method are +extremely implementation-specific, and I'm not sure that there is that +much point trying to describe the internal protocol such that it could +be customized without going to look at the source code. ] + +@code{class-redefinition @var{(old )} @var{(new )}} +(method) + +@itemize @bullet +@item +@code{remove-class-accessors! @var{old}} (generic) + +@item +@code{update-direct-method! @var{method} @var{old} @var{new}} (generic) + +@item +@code{update-direct-subclass! @var{subclass} @var{old} @var{new}} (generic) +@end itemize + +The default @code{update-direct-subclass!} method invokes +@code{class-redefinition} recursively to handle the redefinition of the +subclass. + +When a class is redefined, any existing instance of the redefined class +will be modified for the new class definition before the next time that +any of the instance's slot is referenced or set. GOOPS modifies each +instance by calling the generic function @code{change-class}. [ *fixme* +Actually it sometimes calls @code{change-class} and sometimes +@code{change-object-class}, and I don't understand why. ] + +The default @code{change-class} method copies slot values from the old +to the modified instance, and initializes new slots, as described in +@ref{Changing the Class of an Instance}. After doing so, it makes a +generic function invocation that can be used to customize the instance +update algorithm. + +@code{change-class @var{(old-instance )} @var{(new )}} (method) + +@itemize @bullet +@item +@code{update-instance-for-different-class @var{old-instance} @var{new-instance}} (generic) + +@code{change-class} invokes @code{update-instance-for-different-class} +as the last thing that it does before returning. The applied method can +make any further adjustments to @var{new-instance} that are required to +complete or modify the change of class. The return value from the +applied method is ignored. + +The default @code{update-instance-for-different-class} method does +nothing. +@end itemize + +@node Method Definition +@section Method Definition + +@code{define-method} (syntax) + +@itemize @bullet +@item +@code{add-method! @var{target} @var{method}} (generic) + +@code{define-method} invokes the @code{add-method!} generic function to +handle adding the new method to a variety of possible targets. GOOPS +includes methods to handle @var{target} as + +@itemize @bullet +@item +a generic function (the most common case) + +@item +a procedure + +@item +a primitive generic (@pxref{Extending Guiles Primitives}) +@end itemize + +By defining further methods for @code{add-method!}, you can +theoretically handle adding methods to further types of target. +@end itemize + +@node Generic Function Invocation +@section Generic Function Invocation + +[ *fixme* Description required here. ] + +@code{apply-generic} + +@itemize @bullet +@item +@code{no-method} + +@item +@code{compute-applicable-methods} + +@item +@code{sort-applicable-methods} + +@item +@code{apply-methods} + +@item +@code{no-applicable-method} +@end itemize + +@code{sort-applicable-methods} + +@itemize @bullet +@item +@code{method-more-specific?} +@end itemize + +@code{apply-methods} + +@itemize @bullet +@item +@code{apply-method} +@end itemize + +@code{next-method} + +@itemize @bullet +@item +@code{no-next-method} +@end itemize + +@node Tutorial, Index, MOP Specification, Top +@chapter Tutorial +@include goops-tutorial.texi + +@node Index, Concept Index, Tutorial, Top +@chapter Index +@page +@node Concept Index, Function and Variable Index, Index, Top +@unnumberedsec Concept Index + +@printindex cp + +@node Function and Variable Index, , Concept Index, Top +@unnumberedsec Function and Variable Index + +@printindex fn + +@summarycontents +@contents +@bye diff --git a/doc/goops/hierarchy.eps b/doc/goops/hierarchy.eps new file mode 100644 index 000000000..7b1a98605 --- /dev/null +++ b/doc/goops/hierarchy.eps @@ -0,0 +1,127 @@ +%!PS-Adobe-2.0 EPSF +%%Title: /tmp/xfig-fig016295 +%%Creator: fig2dev +%%CreationDate: Fri Jun 10 23:18:16 1994 +%%For: eg@kaolin (Erick Gallesio) +%%BoundingBox: 0 0 361 217 +%%Pages: 0 +%%EndComments +/$F2psDict 200 dict def +$F2psDict begin +$F2psDict /mtrx matrix put +/l {lineto} bind def +/m {moveto} bind def +/s {stroke} bind def +/n {newpath} bind def +/gs {gsave} bind def +/gr {grestore} bind def +/clp {closepath} bind def +/graycol {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul +4 -2 roll mul setrgbcolor} bind def +/col-1 {} def +/col0 {0 0 0 setrgbcolor} bind def +/col1 {0 0 1 setrgbcolor} bind def +/col2 {0 1 0 setrgbcolor} bind def +/col3 {0 1 1 setrgbcolor} bind def +/col4 {1 0 0 setrgbcolor} bind def +/col5 {1 0 1 setrgbcolor} bind def +/col6 {1 1 0 setrgbcolor} bind def +/col7 {1 1 1 setrgbcolor} bind def + end +/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def +/$F2psEnd {$F2psEnteredState restore end} def +%%EndProlog + +$F2psBegin +0 setlinecap 0 setlinejoin +-216.0 288.0 translate 0.900 -0.900 scale +0.500 setlinewidth +n 309 159 m 309 159 l gs col-1 s gr +n 246.401 216.889 m 244.000 209.000 l 249.831 214.831 l gs 2 setlinejoin col-1 s gr +% Polyline +n 244 209 m 274 259 l gs col-1 s gr +n 298.169 214.831 m 304.000 209.000 l 301.599 216.889 l gs 2 setlinejoin col-1 s gr +% Polyline +n 304 209 m 274 259 l gs col-1 s gr +n 255.721 213.778 m 249.000 209.000 l 257.179 210.053 l gs 2 setlinejoin col-1 s gr +% Polyline +n 249 209 m 364 254 l gs col-1 s gr +n 370.312 216.376 m 374.000 209.000 l 374.217 217.243 l gs 2 setlinejoin col-1 s gr +% Polyline +n 374 209 m 364 254 l gs col-1 s gr +n 283.772 280.725 m 279.000 274.000 l 286.376 277.688 l gs 2 setlinejoin col-1 s gr +% Polyline +n 279 274 m 314 304 l gs col-1 s gr +n 351.457 272.333 m 359.000 269.000 l 353.913 275.490 l gs 2 setlinejoin col-1 s gr +% Polyline +n 359 269 m 314 304 l gs col-1 s gr +n 300.950 165.789 m 309.000 164.000 l 302.739 169.367 l gs 2 setlinejoin col-1 s gr +% Polyline +n 309 164 m 249 194 l gs col-1 s gr +n 307.000 172.000 m 309.000 164.000 l 311.000 172.000 l gs 2 setlinejoin col-1 s gr +% Polyline +n 309 164 m 309 199 l gs col-1 s gr +n 315.261 169.367 m 309.000 164.000 l 317.050 165.789 l gs 2 setlinejoin col-1 s gr +% Polyline +n 309 164 m 379 199 l gs col-1 s gr +n 406.949 101.701 m 404.000 94.000 l 410.226 99.407 l gs 2 setlinejoin col-1 s gr +% Polyline +n 404 94 m 439 144 l gs col-1 s gr +n 410.363 99.245 m 404.000 94.000 l 412.083 95.634 l gs 2 setlinejoin col-1 s gr +% Polyline +n 404 94 m 509 144 l gs col-1 s gr +n 411.173 98.068 m 404.000 94.000 l 412.243 94.214 l gs 2 setlinejoin col-1 s gr +% Polyline +n 404 94 m 584 144 l gs col-1 s gr +n 396.075 96.277 m 404.000 94.000 l 398.079 99.739 l gs 2 setlinejoin col-1 s gr +% Polyline +n 404 94 m 309 149 l gs col-1 s gr +% Polyline +n 584 229 m 584 204 l gs col-1 s gr +n 582.000 212.000 m 584.000 204.000 l 586.000 212.000 l gs 2 setlinejoin col-1 s gr +% Polyline +n 584 189 m 584 159 l gs col-1 s gr +n 582.000 167.000 m 584.000 159.000 l 586.000 167.000 l gs 2 setlinejoin col-1 s gr +/Times-Bold findfont 12.00 scalefont setfont +239 209 m +gs 1 -1 scale (A) col-1 show gr +/Times-Bold findfont 12.00 scalefont setfont +274 274 m +gs 1 -1 scale (D) col-1 show gr +/Times-Bold findfont 12.00 scalefont setfont +359 269 m +gs 1 -1 scale (E) col-1 show gr +/Times-Bold findfont 12.00 scalefont setfont +304 209 m +gs 1 -1 scale (B) col-1 show gr +/Times-Bold findfont 12.00 scalefont setfont +374 209 m +gs 1 -1 scale (C) col-1 show gr +/Times-Bold findfont 12.00 scalefont setfont +314 319 m +gs 1 -1 scale (F) col-1 show gr +/Times-Bold findfont 12.00 scalefont setfont +289 159 m +gs 1 -1 scale () col-1 show gr +/Times-Bold findfont 12.00 scalefont setfont +389 89 m +gs 1 -1 scale () col-1 show gr +/Times-Bold findfont 12.00 scalefont setfont +424 154 m +gs 1 -1 scale () col-1 show gr +/Times-Bold findfont 12.00 scalefont setfont +474 154 m +gs 1 -1 scale () col-1 show gr +/Times-Bold findfont 12.00 scalefont setfont +559 154 m +gs 1 -1 scale () col-1 show gr +/Times-Bold findfont 12.00 scalefont setfont +629 154 m +gs 1 -1 scale (...) col-1 show gr +/Times-Bold findfont 12.00 scalefont setfont +569 199 m +gs 1 -1 scale () col-1 show gr +/Times-Bold findfont 12.00 scalefont setfont +559 239 m +gs 1 -1 scale () col-1 show gr +$F2psEnd diff --git a/doc/goops/hierarchy.txt b/doc/goops/hierarchy.txt new file mode 100644 index 000000000..c7992df7b --- /dev/null +++ b/doc/goops/hierarchy.txt @@ -0,0 +1,14 @@ + + / \\\_____________________ + / \\___________ \ + / \ \ \ + + / | \ | + / | \ | + A B C + |\__/__ | | + \ / \ / | + D E + \ / | + F | + diff --git a/doc/goops/mop.text b/doc/goops/mop.text new file mode 100644 index 000000000..0180f2c1e --- /dev/null +++ b/doc/goops/mop.text @@ -0,0 +1,66 @@ +*** NOTE: This information needs updating! *** + +P - procedure +L - local procedure +S - syntax +G - generic +M - method + +define-class (S) + make-class (S) + ensure-metaclass (P) + ensure-metaclass-with-supers (P) + make (G) + ensure-class (P) + make (G) + class-redefinition (G) + remove-class-accessors (G) + update-direct-method (G) + update-direct-subclass (G) + +define-generic (S) + make-generic-function (S) + ensure-generic-function (P) + make (G) + +define-method (S) + ensure-method (P) + ensure-generic-function (P) + make (G) + make (G) + add-method (P) + +method (S) + ensure-method (P) + +initialize (class) (M) + compute-cpl (P) + compute-slots (G) + compute-getters-n-setters (P) + compute-slot-init-function (L) + compute-get-n-set (G) + compute-slot-accessors (P) + ensure-method (P) + %inherit-magic! (P) + %prep-layout! (P) + +initialize (generic) (M) + make (G) + +change-class (G) + change-object-class (P) + update-instance-for-different-class (G) + +make = make-instance (G) + allocate-instance (G) + %allocate-instance (P) + initialize (G) + %initialize-object (P) + +apply-generic (G) + compute-applicable-methods (G) + find-method (P) + sort-applicable-methods (G) + sort (P) + apply-methods (G) + apply-method (G) diff --git a/doc/r5rs/.cvsignore b/doc/r5rs/.cvsignore new file mode 100644 index 000000000..407face4c --- /dev/null +++ b/doc/r5rs/.cvsignore @@ -0,0 +1,22 @@ +Makefile +Makefile.in +stamp-vti +stamp-vti.1 +*.log +*.dvi +*.aux +*.toc +*.cp +*.fn +*.vr +*.tp +*.ky +*.pg +*.pgs +*.cps +*.fns +*.tps +*.vrs +*.ps +*.info* +*.html diff --git a/doc/r5rs/Makefile.am b/doc/r5rs/Makefile.am new file mode 100644 index 000000000..231c7bfeb --- /dev/null +++ b/doc/r5rs/Makefile.am @@ -0,0 +1,24 @@ +## Process this file with Automake to create Makefile.in +## +## Copyright (C) 1998 Free Software Foundation, Inc. +## +## This file is part of GUILE. +## +## GUILE is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as +## published by the Free Software Foundation; either version 2, or +## (at your option) any later version. +## +## GUILE is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public +## License along with GUILE; see the file COPYING. If not, write +## to the Free Software Foundation, Inc., 59 Temple Place, Suite +## 330, Boston, MA 02111-1307 USA + +AUTOMAKE_OPTIONS = gnu + +info_TEXINFOS = r5rs.texi diff --git a/doc/r5rs/r5rs.texi b/doc/r5rs/r5rs.texi new file mode 100644 index 000000000..a33771190 --- /dev/null +++ b/doc/r5rs/r5rs.texi @@ -0,0 +1,8538 @@ +\input texinfo @c -*-texinfo-*- +@c %**start of header +@setfilename r5rs.info +@settitle Revised(5) Scheme + +@c This copy of r5rs.texi differs from Aubrey Jaffer's master copy +@c by a set of changes to allow the building of r5rs.dvi from r5rs.texi. +@c Aubrey Jaffer's view - which I agree with - is that, given that +@c people have the option of building r5rs.dvi from the original +@c LaTeX distribution for R5RS, it is not worth fixing his master +@c copy of r5rs.texi and the tool which autogenerates it. On the +@c other hand, it is a marginal convenience for people to be able to +@c build hardcopy from r5rs.texi, even if the results are less good +@c than with the original LaTeX. Hence the following fixes. +@c (lines 714, 725, 728, 1614, 2258): Remove invalid parentheses from +@c @deffn statements. +@c (line 2316): Change @deffnx to @deffn, and insert `@end deffn' to +@c terminate preceding @deffn. +@c (line 7320): Insert `@c ' at beginning of lines that are intended +@c to be @ignore'd. +@c +@c NJ 2001/1/26 + +@c \documentclass[twoside]{algol60} + +@c \pagestyle{headings} +@c \showboxdepth=0 + + + +@c \def\headertitle{Revised$^{5}$ Scheme} +@c \def\integerversion{5} + +@c Sizes and dimensions + +@c \topmargin -.375in % Nominal distance from top of page to top of + +@c box containing running head. +@c \headsep 15pt % Space between running head and text. + +@c \textheight 663pt % Height of text (including footnotes and figures, + +@c excluding running head and foot). + +@c \textwidth 523pt % Width of text line. +@c \columnsep 15pt % Space between columns +@c \columnseprule 0pt % Width of rule between columns. + +@c \parskip 5pt plus 2pt minus 2pt % Extra vertical space between paragraphs. +@c \parindent 0pt % Width of paragraph indentation. +@c \topsep 0pt plus 2pt % Extra vertical space, in addition to + +@c \parskip, added above and below list and + +@c paragraphing environments. + +@c \oddsidemargin -.5in % Left margin on odd-numbered pages. +@c \evensidemargin -.5in % Left margin on even-numbered pages. + +@c % End of sizes and dimensions + +@paragraphindent 0 +@c %**end of header +@c syncodeindex fn cp + +@ifinfo +@dircategory The Algorithmic Language Scheme +@direntry +* R5RS: (r5rs). The Revised(5) Report on Scheme. +@end direntry +@end ifinfo + + +@c \parindent 0pt %!! 15pt % Width of paragraph indentation. + + @b{20 February 1998} +@c \hfil \today{} + +@c @include{first} +@titlepage + +@c HTML first page +@title Scheme +@subtitle Revised(5) Report on the Algorithmic Language Scheme +@c First page + +@c \thispagestyle{empty} + +@c \todo{"another" report?} + + +@author R@sc{ICHARD} K@sc{ELSEY}, W@sc{ILLIAM} C@sc{LINGER, AND} J@sc{ONATHAN} R@sc{EES} (@i{Editors}) +@author H. A@sc{BELSON} +@author R. K. D@sc{YBVIG} +@author C. T. H@sc{AYNES} +@author G. J. R@sc{OZAS} +@author N. I. A@sc{DAMS IV} +@author D. P. F@sc{RIEDMAN} +@author E. K@sc{OHLBECKER} +@author G. L. S@sc{TEELE} J@sc{R}. +@author D. H. B@sc{ARTLEY} +@author R. H@sc{ALSTEAD} +@author D. O@sc{XLEY} +@author G. J. S@sc{USSMAN} +@author G. B@sc{ROOKS} +@author C. H@sc{ANSON} +@author K. M. P@sc{ITMAN} +@author M. W@sc{AND} +@author + + +@c {\it Dedicated to the Memory of ALGOL 60} +@i{Dedicated to the Memory of Robert Hieb} +@c [For the macros in R5RS -RK] + + + + +@unnumbered Summary + + +The report gives a defining description of the programming language +Scheme. Scheme is a statically scoped and properly tail-recursive +dialect of the Lisp programming language invented by Guy Lewis +Steele Jr.@: and Gerald Jay Sussman. It was designed to have an +exceptionally clear and simple semantics and few different ways to +form expressions. A wide variety of programming paradigms, including +imperative, functional, and message passing styles, find convenient +expression in Scheme. + +The introduction offers a brief history of the language and of +the report. + +The first three chapters present the fundamental ideas of the +language and describe the notational conventions used for describing the +language and for writing programs in the language. + +Chapters @ref{Expressions} and @ref{Program structure} describe +the syntax and semantics of expressions, programs, and definitions. + +Chapter @ref{Standard procedures} describes Scheme's built-in +procedures, which include all of the language's data manipulation and +input/output primitives. + +Chapter @ref{Formal syntax and semantics} provides a formal syntax for Scheme +written in extended BNF, along with a formal denotational semantics. +An example of the use of the language follows the formal syntax and +semantics. + +The report concludes with a list of references and an +alphabetic index. + +@ignore todo +expand the summary so that it fills up the column. +@end ignore + + +@c \vfill +@c \begin{center} +@c {\large \bf +@c *** DRAFT*** \\ +@c %August 31, 1989 +@c \today +@c }\end{center} + + + + + +@c \addvspace{3.5pt} % don't shrink this gap +@c \renewcommand{\tocshrink}{-3.5pt} % value determined experimentally + + + + + + +@page + +@end titlepage + +@c INFO first page +@ifinfo + +@c First page + +@c \thispagestyle{empty} + +@c \todo{"another" report?} + + +@node top, Introduction, (dir), (dir) +@top Revised(5) Report on the Algorithmic Language Scheme + +@sp 1 + + +@center @c begin-tabular +@quotation +@multitable @columnfractions 0.25 0.25 0.25 0.25 +@item +@center R@sc{ICHARD} K@sc{ELSEY}, W@sc{ILLIAM} C@sc{LINGER, AND} J@sc{ONATHAN} R@sc{EES} (@i{Editors}) +@item H. A@sc{BELSON} @tab R. K. D@sc{YBVIG} @tab C. T. H@sc{AYNES} @tab G. J. R@sc{OZAS} +@item N. I. A@sc{DAMS IV} @tab D. P. F@sc{RIEDMAN} @tab E. K@sc{OHLBECKER} @tab G. L. S@sc{TEELE} J@sc{R}. +@item D. H. B@sc{ARTLEY} @tab R. H@sc{ALSTEAD} @tab D. O@sc{XLEY} @tab G. J. S@sc{USSMAN} +@item G. B@sc{ROOKS} @tab C. H@sc{ANSON} @tab K. M. P@sc{ITMAN} @tab M. W@sc{AND} +@item +@end multitable +@end quotation + + +@sp 2 + +@c {\it Dedicated to the Memory of ALGOL 60} +@i{Dedicated to the Memory of Robert Hieb} +@c [For the macros in R5RS -RK] + +@sp 3 + + + + +@majorheading Summary + + +The report gives a defining description of the programming language +Scheme. Scheme is a statically scoped and properly tail-recursive +dialect of the Lisp programming language invented by Guy Lewis +Steele Jr.@: and Gerald Jay Sussman. It was designed to have an +exceptionally clear and simple semantics and few different ways to +form expressions. A wide variety of programming paradigms, including +imperative, functional, and message passing styles, find convenient +expression in Scheme. + +The introduction offers a brief history of the language and of +the report. + +The first three chapters present the fundamental ideas of the +language and describe the notational conventions used for describing the +language and for writing programs in the language. + +Chapters @ref{Expressions} and @ref{Program structure} describe +the syntax and semantics of expressions, programs, and definitions. + +Chapter @ref{Standard procedures} describes Scheme's built-in +procedures, which include all of the language's data manipulation and +input/output primitives. + +Chapter @ref{Formal syntax and semantics} provides a formal syntax for Scheme +written in extended BNF, along with a formal denotational semantics. +An example of the use of the language follows the formal syntax and +semantics. + +The report concludes with a list of references and an +alphabetic index. + +@ignore todo +expand the summary so that it fills up the column. +@end ignore + + +@c \vfill +@c \begin{center} +@c {\large \bf +@c *** DRAFT*** \\ +@c %August 31, 1989 +@c \today +@c }\end{center} + + + + + +@c \addvspace{3.5pt} % don't shrink this gap +@c \renewcommand{\tocshrink}{-3.5pt} % value determined experimentally + +@unnumbered Contents + +@menu +* Introduction:: +* Overview of Scheme:: +* Lexical conventions:: +* Basic concepts:: +* Expressions:: +* Program structure:: +* Standard procedures:: +* Formal syntax and semantics:: +* Notes:: +* Additional material:: +* Example:: +* Bibliography:: +* Index:: +@end menu + + + + + +@page + +@end ifinfo + + +@c @include{intro} +@node Introduction, Overview of Scheme, top, top +@unnumbered Introduction + +@menu +* Background:: +* Acknowledgements:: +@end menu + + + + +Programming languages should be designed not by piling feature on top of +feature, but by removing the weaknesses and restrictions that make additional +features appear necessary. Scheme demonstrates that a very small number +of rules for forming expressions, with no restrictions on how they are +composed, suffice to form a practical and efficient programming language +that is flexible enough to support most of the major programming +paradigms in use today. + +@c Scheme has influenced the evolution of Lisp. +Scheme +was one of the first programming languages to incorporate first class +procedures as in the lambda calculus, thereby proving the usefulness of +static scope rules and block structure in a dynamically typed language. +Scheme was the first major dialect of Lisp to distinguish procedures +from lambda expressions and symbols, to use a single lexical +environment for all variables, and to evaluate the operator position +of a procedure call in the same way as an operand position. By relying +entirely on procedure calls to express iteration, Scheme emphasized the +fact that tail-recursive procedure calls are essentially goto's that +pass arguments. Scheme was the first widely used programming language to +embrace first class escape procedures, from which all previously known +sequential control structures can be synthesized. A subsequent +version of Scheme introduced the concept of exact and inexact numbers, +an extension of Common Lisp's generic arithmetic. +More recently, Scheme became the first programming language to support +hygienic macros, which permit the syntax of a block-structured language +to be extended in a consistent and reliable manner. +@c A few +@c of these innovations have recently been incorporated into Common Lisp, while +@c others remain to be adopted. + +@ignore todo +Ramsdell: +I would like to make a few comments on presentation. The most +important comment is about section organization. Newspaper writers +spend most of their time writing the first three paragraphs of any +article. This part of the article is often the only part read by +readers, and is important in enticing readers to continue. In the +same way, The first page is most likely to be the only page read by +many SIGPLAN readers. If I had my choice of what I would ask them to +read, it would be the material in section 1.1, the Semantics section +that notes that scheme is lexically scoped, tail recursive, weakly +typed, ... etc. I would expand on the discussion on continuations, +as they represent one important difference between Scheme and other +languages. The introduction, with its history of scheme, its history +of scheme reports and meetings, and acknowledgements giving names of +people that the reader will not likely know, is not that one page I +would like all to read. I suggest moving the history to the back of +the report, and use the first couple of pages to convince the reader +that the language documented in this report is worth studying. + +@end ignore + + +@node Background, Acknowledgements, Introduction, Introduction +@unnumberedsec Background + + +The first description of Scheme was written in +1975 [Scheme75]. A revised report [Scheme78] +@ignore todo +italicize or not? +@end ignore + appeared in 1978, which described the evolution +of the language as its MIT implementation was upgraded to support an +innovative compiler [Rabbit]. Three distinct projects began in +1981 and 1982 to use variants of Scheme for courses at MIT, Yale, and +Indiana University [Rees82], [MITScheme], [Scheme311]. An introductory +computer science textbook using Scheme was published in +1984 [SICP]. + +@c \vest As might be expected of a language used primarily for education and +@c research, Scheme has always evolved rapidly. This was no problem when +@c Scheme was used only within MIT, but +As Scheme became more widespread, +local dialects began to diverge until students and researchers +occasionally found it difficult to understand code written at other +sites. +Fifteen representatives of the major implementations of Scheme therefore +met in October 1984 to work toward a better and more widely accepted +standard for Scheme. +@c Participating in this workshop were Hal Abelson, Norman Adams, David +@c Bartley, Gary Brooks, William Clinger, Daniel Friedman, Robert Halstead, +@c Chris Hanson, Christopher Haynes, Eugene Kohlbecker, Don Oxley, Jonathan Rees, +@c Guillermo Rozas, Gerald Jay Sussman, and Mitchell Wand. Kent Pitman +@c made valuable contributions to the agenda for the workshop but was +@c unable to attend the sessions. + +@c Subsequent electronic mail discussions and committee work completed the +@c definition of the language. +@c Gerry Sussman drafted the section on numbers, Chris Hanson drafted the +@c sections on characters and strings, and Gary Brooks and William Clinger +@c drafted the sections on input and output. +@c William Clinger recorded the decisions of the workshop and +@c compiled the pieces into a coherent document. +@c The ``Revised revised report on Scheme''~\cite{RRRS} +Their report [RRRS] +was published at MIT and Indiana University in the summer of 1985. +Further revision took place in the spring of 1986 [R3RS], +@c , again accomplished +@c almost entirely by electronic mail, resulted in the present report. +and in the spring of 1988 [R4RS]. +The present report reflects further revisions agreed upon in a meeting +at Xerox PARC in June 1992. + +@c \vest The number 3 in the title is part of the title, not a reference to +@c a footnote. The word ``revised'' is raised to the third power because +@c the report is a revision of a report that was already twice revised. + +@ignore todo +Write an editors' note? +@end ignore + + + +@sp 3 + +We intend this report to belong to the entire Scheme community, and so +we grant permission to copy it in whole or in part without fee. In +particular, we encourage implementors of Scheme to use this report as +a starting point for manuals and other documentation, modifying it as +necessary. + + + + +@node Acknowledgements, , Background, Introduction +@unnumberedsec Acknowledgements + + +We would like to thank the following people for their help: Alan Bawden, Michael +Blair, George Carrette, Andy Cromarty, Pavel Curtis, Jeff Dalton, Olivier Danvy, +Ken Dickey, Bruce Duba, Marc Feeley, +Andy Freeman, Richard Gabriel, Yekta G"ursel, Ken Haase, Robert +Hieb, Paul Hudak, Morry Katz, Chris Lindblad, Mark Meyer, Jim Miller, Jim Philbin, +John Ramsdell, Mike Shaff, Jonathan Shapiro, Julie Sussman, +Perry Wagle, Daniel Weise, Henry Wu, and Ozan Yigit. +We thank Carol Fessenden, Daniel +Friedman, and Christopher Haynes for permission to use text from the Scheme 311 +version 4 reference manual. We thank Texas Instruments, Inc. for permission to +use text from the @emph{TI Scheme Language Reference Manual}[TImanual85]. +We gladly acknowledge the influence of manuals for MIT Scheme[MITScheme], +T[Rees84], Scheme 84[Scheme84],Common Lisp[CLtL], +and Algol 60[Naur63]. + +We also thank Betty Dexter for the extreme effort she put into +setting this report in @TeX{}, and Donald Knuth for designing the program +that caused her troubles. + +The Artificial Intelligence Laboratory of the +Massachusetts Institute of Technology, the Computer Science +Department of Indiana University, the Computer and Information +Sciences Department of the University of Oregon, and the NEC Research +Institute supported the preparation of this report. Support for the MIT +work was provided in part by +the Advanced Research Projects Agency of the Department of Defense under Office +of Naval Research contract N00014-80-C-0505. Support for the Indiana +University work was provided by NSF grants NCS 83-04567 and NCS +83-03325. + + + + +@sp 2 + +@c \clearchapterstar{Description of the language} %\unskip\vskip -2ex +@c @include{struct} + +@c 1. Structure of the language + +@node Overview of Scheme, Lexical conventions, Introduction, top +@chapter Overview of Scheme + +@menu +* Semantics:: +* Syntax:: +* Notation and terminology:: +@end menu + + +@node Semantics, Syntax, Overview of Scheme, Overview of Scheme +@section Semantics + + + +This section gives an overview of Scheme's semantics. A +detailed informal semantics is the subject of +chapters @ref{Basic concepts} through @ref{Standard procedures}. For reference +purposes, section @ref{Formal semantics} provides a formal +semantics of Scheme. + +Following Algol, Scheme is a statically scoped programming +language. Each use of a variable is associated with a lexically +apparent binding of that variable. + +Scheme has latent as opposed to manifest types. Types +are associated with values (also called objects) rather than +@cindex @w{object} +with variables. (Some authors refer to languages with latent types as +weakly typed or dynamically typed languages.) Other languages with +latent types are APL, Snobol, and other dialects of Lisp. Languages +with manifest types (sometimes referred to as strongly typed or +statically typed languages) include Algol 60, Pascal, and C. + +All objects created in the course of a Scheme computation, including +procedures and continuations, have unlimited extent. +No Scheme object is ever destroyed. The reason that +implementations of Scheme do not (usually!) run out of storage is that +they are permitted to reclaim the storage occupied by an object if +they can prove that the object cannot possibly matter to any future +computation. Other languages in which most objects have unlimited +extent include APL and other Lisp dialects. + +Implementations of Scheme are required to be properly tail-recursive. +This allows the execution of an iterative computation in constant space, +even if the iterative computation is described by a syntactically +recursive procedure. Thus with a properly tail-recursive implementation, +iteration can be expressed using the ordinary procedure-call +mechanics, so that special iteration constructs are useful only as +syntactic sugar. See section @ref{Proper tail recursion}. + +Scheme procedures are objects in their own right. Procedures can be +created dynamically, stored in data structures, returned as results of +procedures, and so on. Other languages with these properties include +Common Lisp and ML. +@ignore todo +Rozas: Scheme had them first. +@end ignore + + +One distinguishing feature of Scheme is that continuations, which +in most other languages only operate behind the scenes, also have +``first-class'' status. Continuations are useful for implementing a +wide variety of advanced control constructs, including non-local exits, +backtracking, and coroutines. See section @ref{Control features}. + +Arguments to Scheme procedures are always passed by value, which +means that the actual argument expressions are evaluated before the +procedure gains control, whether the procedure needs the result of the +evaluation or not. ML, C, and APL are three other languages that always +pass arguments by value. +This is distinct from the lazy-evaluation semantics of Haskell, +or the call-by-name semantics of Algol 60, where an argument +expression is not evaluated unless its value is needed by the +procedure. + +@ignore todo +Lisp's call by value should be explained more +accurately. What's funny is that all values are references. +@end ignore + + +Scheme's model of arithmetic is designed to remain as independent as +possible of the particular ways in which numbers are represented within a +computer. In Scheme, every integer is a rational number, every rational is a +real, and every real is a complex number. Thus the distinction between integer +and real arithmetic, so important to many programming languages, does not +appear in Scheme. In its place is a distinction between exact arithmetic, +which corresponds to the mathematical ideal, and inexact arithmetic on +approximations. As in Common Lisp, exact arithmetic is not limited to +integers. + +@node Syntax, Notation and terminology, Semantics, Overview of Scheme +@section Syntax + + +Scheme, like most dialects of Lisp, employs a fully parenthesized prefix +notation for programs and (other) data; the grammar of Scheme generates a +sublanguage of the language used for data. An important +consequence of this simple, uniform representation is the susceptibility of +Scheme programs and data to uniform treatment by other Scheme programs. +For example, the @samp{eval} procedure evaluates a Scheme program expressed +as data. + +The @samp{read} procedure performs syntactic as well as lexical decomposition of +the data it reads. The @samp{read} procedure parses its input as data +(section @pxref{External representation}), not as program. + +The formal syntax of Scheme is described in section @ref{Formal syntax}. + + +@node Notation and terminology, , Syntax, Overview of Scheme +@section Notation and terminology + +@menu +* Primitive; library; and optional features:: +* Error situations and unspecified behavior:: +* Entry format:: +* Evaluation examples:: +* Naming conventions:: +@end menu + + + +@node Primitive; library; and optional features, Error situations and unspecified behavior, Notation and terminology, Notation and terminology +@subsection Primitive; library; and optional features + + + +It is required that every implementation of Scheme support all +features that are not marked as being @dfn{optional}. Implementations are +@cindex @w{optional} +free to omit optional features of Scheme or to add extensions, +provided the extensions are not in conflict with the language reported +here. In particular, implementations must support portable code by +providing a syntactic mode that preempts no lexical conventions of this +report. + +To aid in understanding and implementing Scheme, some features are marked +as @dfn{library}. These can be easily implemented in terms of the other, +@cindex @w{library} +primitive, features. They are redundant in the strict sense of +the word, but they capture common patterns of usage, and are therefore +provided as convenient abbreviations. + +@node Error situations and unspecified behavior, Entry format, Primitive; library; and optional features, Notation and terminology +@subsection Error situations and unspecified behavior + + + +@cindex @w{error} +When speaking of an error situation, this report uses the phrase ``an +error is signalled'' to indicate that implementations must detect and +report the error. If such wording does not appear in the discussion of +an error, then implementations are not required to detect or report the +error, though they are encouraged to do so. An error situation that +implementations are not required to detect is usually referred to simply +as ``an error.'' + +For example, it is an error for a procedure to be passed an argument that +the procedure is not explicitly specified to handle, even though such +domain errors are seldom mentioned in this report. Implementations may +extend a procedure's domain of definition to include such arguments. + +This report uses the phrase ``may report a violation of an +implementation restriction'' to indicate circumstances under which an +implementation is permitted to report that it is unable to continue +execution of a correct program because of some restriction imposed by the +implementation. Implementation restrictions are of course discouraged, +but implementations are encouraged to report violations of implementation +restrictions. +@cindex @w{implementation restriction} + +For example, an implementation may report a violation of an +implementation restriction if it does not have enough storage to run a +program. + +If the value of an expression is said to be ``unspecified,'' then +the expression must evaluate to some object without signalling an error, +but the value depends on the implementation; this report explicitly does +not say what value should be returned. +@cindex @w{unspecified} + +@ignore todo +Talk about unspecified behavior vs. unspecified values. +@end ignore + + +@ignore todo +Look at KMP's situations paper. +@end ignore + + + +@node Entry format, Evaluation examples, Error situations and unspecified behavior, Notation and terminology +@subsection Entry format + + +Chapters @ref{Expressions} and @ref{Standard procedures} are organized +into entries. Each entry describes one language feature or a group of +related features, where a feature is either a syntactic construct or a +built-in procedure. An entry begins with one or more header lines of the form + + +@noindent +@deffn {@var{category}} @var{template} + +@end deffn + +for required, primitive features, or + + +@noindent +@deffn {@var{qualifier} @var{category}} @var{template} + +@end deffn + +where @var{qualifier} is either ``library'' or ``optional'' as defined + in section @ref{Primitive; library; and optional features}. + +If @var{category} is ``syntax'', the entry describes an expression +type, and the template gives the syntax of the expression type. +Components of expressions are designated by syntactic variables, which +are written using angle brackets, for example, @r{}, +@r{}. Syntactic variables should be understood to denote segments of +program text; for example, @r{} stands for any string of +characters which is a syntactically valid expression. The notation + +@format + @r{} @dots{} +@end format + +indicates zero or more occurrences of a @r{}, and + +@format + @r{} @r{} @dots{} +@end format + +indicates one or more occurrences of a @r{}. + +If @var{category} is ``procedure'', then the entry describes a procedure, and +the header line gives a template for a call to the procedure. Argument +names in the template are @var{italicized}. Thus the header line + + +@noindent +@deffn {procedure} vector-ref @var{vector} @var{k} + +@end deffn + +indicates that the built-in procedure @t{vector-ref} takes +two arguments, a vector @var{vector} and an exact non-negative integer +@var{k} (see below). The header lines + + +@noindent + +@deffn {procedure} make-vector @var{k} + + +@deffnx {procedure} make-vector @var{k} @var{fill} + +@end deffn + +indicate that the @t{make-vector} procedure must be defined to take +either one or two arguments. + + +It is an error for an operation to be presented with an argument that it +is not specified to handle. For succinctness, we follow the convention +that if an argument name is also the name of a type listed in +section @ref{Disjointness of types}, then that argument must be of the named type. +For example, the header line for @t{vector-ref} given above dictates that the +first argument to @t{vector-ref} must be a vector. The following naming +conventions also imply type restrictions: +@c \newcommand{\foo}[1]{\vr{#1}, \vri{#1}, $\ldots$ \vrj{#1}, $\ldots$} + + +@center @c begin-tabular +@quotation +@table @asis +@item @var{obj} +any object +@item @var{list}, @var{list1}, @dots{} @var{listj}, @dots{} +list (see section @pxref{Pairs and lists}) +@item @var{z}, @var{z1}, @dots{} @var{zj}, @dots{} +complex number +@item @var{x}, @var{x1}, @dots{} @var{xj}, @dots{} +real number +@item @var{y}, @var{y1}, @dots{} @var{yj}, @dots{} +real number +@item @var{q}, @var{q1}, @dots{} @var{qj}, @dots{} +rational number +@item @var{n}, @var{n1}, @dots{} @var{nj}, @dots{} +integer +@item @var{k}, @var{k1}, @dots{} @var{kj}, @dots{} +exact non-negative integer +@item +@end table +@end quotation + + + + +@ignore todo +Provide an example entry?? +@end ignore + + + +@node Evaluation examples, Naming conventions, Entry format, Notation and terminology +@subsection Evaluation examples + + +The symbol ``@result{}'' used in program examples should be read +``evaluates to.'' For example, + + +@example + +(* 5 8) ==> 40 + +@end example + + +means that the expression @t{(* 5 8)} evaluates to the object @t{40}. +Or, more precisely: the expression given by the sequence of characters +``@t{(* 5 8)}'' evaluates, in the initial environment, to an object +that may be represented externally by the sequence of characters ``@t{40}''. See section @ref{External representations} for a discussion of external +representations of objects. + +@node Naming conventions, , Evaluation examples, Notation and terminology +@subsection Naming conventions + + +By convention, the names of procedures that always return a boolean +value usually end +in ``@code{?}''. Such procedures are called predicates. +@vindex @w{?} + +By convention, the names of procedures that store values into previously +allocated locations (see section @pxref{Storage model}) usually end in +``@code{!}''. +@vindex @w{!} +Such procedures are called mutation procedures. +By convention, the value returned by a mutation procedure is unspecified. + +By convention, ``@code{->}'' appears within the names of procedures that +@vindex @w{->} +take an object of one type and return an analogous object of another type. +For example, @samp{list->vector} takes a list and returns a vector whose +elements are the same as those of the list. + + + +@ignore todo +Terms that need defining: thunk, command (what else?). +@end ignore + + +@c @include{lex} + +@c Lexical structure + +@c %\vfill\eject +@node Lexical conventions, Basic concepts, Overview of Scheme, top +@chapter Lexical conventions + +@menu +* Identifiers:: +* Whitespace and comments:: +* Other notations:: +@end menu + + +This section gives an informal account of some of the lexical +conventions used in writing Scheme programs. For a formal syntax of +Scheme, see section @ref{Formal syntax}. + +Upper and lower case forms of a letter are never distinguished +except within character and string constants. For example, @samp{Foo} is +the same identifier as @samp{FOO}, and @t{#x1AB} is the same number as +@t{#X1ab}. + +@node Identifiers, Whitespace and comments, Lexical conventions, Lexical conventions +@section Identifiers + + + +Most identifiers allowed by other programming +@cindex @w{identifier} +languages are also acceptable to Scheme. The precise rules for forming +identifiers vary among implementations of Scheme, but in all +implementations a sequence of letters, digits, and ``extended alphabetic +characters'' that begins with a character that cannot begin a number is +an identifier. In addition, @code{+}, @code{-}, and @code{...} are identifiers. +@vindex @w{...} +@vindex @w{-} +@vindex @w{+} +Here are some examples of identifiers: + + +@example + +lambda q +list->vector soup ++ V17a +<=? a34kTMNs +the-word-recursion-has-many-meanings + +@end example + + +Extended alphabetic characters may be used within identifiers as if +they were letters. The following are extended alphabetic characters: + + +@example + +! $ % & * + - . / : < = > ? @@ ^ _ ~ +@end example + + +See section @ref{Lexical structure} for a formal syntax of identifiers. + +Identifiers have two uses within Scheme programs: + + +@itemize @bullet + +@item +Any identifier may be used as a variable +or as a syntactic keyword +(see sections @pxref{Variables; syntactic keywords; and regions} and @pxref{Macros}). + +@item +When an identifier appears as a literal or within a literal +(see section @pxref{Literal expressions}), it is being used to denote a @emph{symbol} +(see section @pxref{Symbols}). + + +@end itemize + +@cindex @w{syntactic keyword} +@cindex @w{variable} + +@c \label{keywordsection} +@c The following identifiers are syntactic keywords, and should not be used +@c as variables: + +@c \begin{scheme} +@c => do or +@c and else quasiquote +@c begin if quote +@c case lambda set! +@c cond let unquote +@c define let* unquote-splicing +@c delay letrec% +@c \end{scheme} + +@c Some implementations allow all identifiers, including syntactic +@c keywords, to be used as variables. This is a compatible extension to +@c the language, but ambiguities in the language result when the +@c restriction is relaxed, and the ways in which these ambiguities are +@c resolved vary between implementations. + + +@node Whitespace and comments, Other notations, Identifiers, Lexical conventions +@section Whitespace and comments + + +@dfn{Whitespace} characters are spaces and newlines. +@cindex @w{Whitespace} +(Implementations typically provide additional whitespace characters such +as tab or page break.) Whitespace is used for improved readability and +as necessary to separate tokens from each other, a token being an +indivisible lexical unit such as an identifier or number, but is +otherwise insignificant. Whitespace may occur between any two tokens, +but not within a token. Whitespace may also occur inside a string, +where it is significant. + +A semicolon (@t{;}) indicates the start of a +comment. The comment continues to the +@cindex @w{;} +@cindex @w{comment} +end of the line on which the semicolon appears. Comments are invisible +to Scheme, but the end of the line is visible as whitespace. This +prevents a comment from appearing in the middle of an identifier or +number. + + +@example + +;;; The FACT procedure computes the factorial +;;; of a non-negative integer. +(define fact + (lambda (n) + (if (= n 0) + 1 ;Base case: return 1 + (* n (fact (- n 1)))))) + +@end example + + + +@node Other notations, , Whitespace and comments, Lexical conventions +@section Other notations + + +@ignore todo +Rewrite? +@end ignore + + +For a description of the notations used for numbers, see +section @ref{Numbers}. + + +@table @t + + +@item @t{.@: + -} +These are used in numbers, and may also occur anywhere in an identifier +except as the first character. A delimited plus or minus sign by itself +is also an identifier. +A delimited period (not occurring within a number or identifier) is used +in the notation for pairs (section @pxref{Pairs and lists}), and to indicate a +rest-parameter in a formal parameter list (section @pxref{Procedures}). +A delimited sequence of three successive periods is also an identifier. + +@item @t{( )} +Parentheses are used for grouping and to notate lists +(section @pxref{Pairs and lists}). + +@item @t{'} +The single quote character is used to indicate literal data (section @pxref{Literal expressions}). + +@item @t{`} +The backquote character is used to indicate almost-constant +data (section @pxref{Quasiquotation}). + +@item @t{, ,@@} +The character comma and the sequence comma at-sign are used in conjunction +with backquote (section @pxref{Quasiquotation}). + +@item @t{"} +The double quote character is used to delimit strings (section @pxref{Strings}). + +@item \ +Backslash is used in the syntax for character constants +(section @pxref{Characters}) and as an escape character within string +constants (section @pxref{Strings}). + +@c A box used because \verb is not allowed in command arguments. + +@item @w{@t{[ ] @{ @} |}} +Left and right square brackets and curly braces and vertical bar +are reserved for possible future extensions to the language. + +@item # + Sharp sign is used for a variety of purposes depending on +the character that immediately follows it: + +@item @t{#t} @t{#f} +These are the boolean constants (section @pxref{Booleans}). + +@item #\ +This introduces a character constant (section @pxref{Characters}). + +@item #@t{(} +This introduces a vector constant (section @pxref{Vectors}). Vector constants +are terminated by @t{)} . + +@item @t{#e #i #b #o #d #x} +These are used in the notation for numbers (section @pxref{Syntax of numerical constants}). + +@end table + + +@c @include{basic} + +@c \vfill\eject +@node Basic concepts, Expressions, Lexical conventions, top +@chapter Basic concepts + +@menu +* Variables; syntactic keywords; and regions:: +* Disjointness of types:: +* External representations:: +* Storage model:: +* Proper tail recursion:: +@end menu + + + +@node Variables; syntactic keywords; and regions, Disjointness of types, Basic concepts, Basic concepts +@section Variables; syntactic keywords; and regions + + + + +An identifier may name a type of syntax, or it may name +@cindex @w{identifier} +a location where a value can be stored. An identifier that names a type +of syntax is called a @emph{syntactic keyword} +@cindex @w{syntactic keyword} +and is said to be @emph{bound} to that syntax. An identifier that names a +location is called a @emph{variable} and is said to be +@cindex @w{variable} +@emph{bound} to that location. The set of all visible +bindings in effect at some point in a program is +@cindex @w{binding} +known as the @emph{environment} in effect at that point. The value +stored in the location to which a variable is bound is called the +variable's value. By abuse of terminology, the variable is sometimes +said to name the value or to be bound to the value. This is not quite +accurate, but confusion rarely results from this practice. + +@ignore todo +Define ``assigned'' and ``unassigned'' perhaps? +@end ignore + + +@ignore todo +In programs without side effects, one can safely pretend that the +variables are bound directly to the arguments. Or: +In programs without @code{set!}, one can safely pretend that the +@vindex @w{set!} +variable is bound directly to the value. +@end ignore + + +Certain expression types are used to create new kinds of syntax +and bind syntactic keywords to those new syntaxes, while other +expression types create new locations and bind variables to those +locations. These expression types are called @emph{binding constructs}. + +@cindex @w{binding construct} +Those that bind syntactic keywords are listed in section @ref{Macros}. +The most fundamental of the variable binding constructs is the +@samp{lambda} expression, because all other variable binding constructs +can be explained in terms of @samp{lambda} expressions. The other +variable binding constructs are @samp{let}, @samp{let*}, @samp{letrec}, +and @samp{do} expressions (see sections @pxref{Procedures}, @pxref{Binding constructs}, and +@pxref{Iteration}). + +@c Note: internal definitions not mentioned here. + +Like Algol and Pascal, and unlike most other dialects of Lisp +except for Common Lisp, Scheme is a statically scoped language with +block structure. To each place where an identifier is bound in a program +there corresponds a @dfn{region} of the program text within which +@cindex @w{region} +the binding is visible. The region is determined by the particular +binding construct that establishes the binding; if the binding is +established by a @samp{lambda} expression, for example, then its region +is the entire @samp{lambda} expression. Every mention of an identifier +refers to the binding of the identifier that established the +innermost of the regions containing the use. If there is no binding of +the identifier whose region contains the use, then the use refers to the +binding for the variable in the top level environment, if any +(chapters @pxref{Expressions} and @pxref{Standard procedures}); if there is no +binding for the identifier, +it is said to be @dfn{unbound}. +@cindex @w{top level environment} +@cindex @w{bound} +@cindex @w{unbound} + +@ignore todo +Mention that some implementations have multiple top level environments? +@end ignore + + +@ignore todo +Pitman sez: needs elaboration in case of @t{(let ...)} +@end ignore + + +@ignore todo +Pitman asks: say something about vars created after scheme starts? +@t{(define x 3) (define (f) x) (define (g) y) (define y 4)} +Clinger replies: The language was explicitly +designed to permit a view in which no variables are created after +Scheme starts. In files, you can scan out the definitions beforehand. +I think we're agreed on the principle that interactive use should +approximate that behavior as closely as possible, though we don't yet +agree on which programming environment provides the best approximation. +@end ignore + + +@node Disjointness of types, External representations, Variables; syntactic keywords; and regions, Basic concepts +@section Disjointness of types + + + +No object satisfies more than one of the following predicates: + + +@example + +boolean? pair? +symbol? number? +char? string? +vector? port? +procedure? + +@end example + + +These predicates define the types @emph{boolean}, @emph{pair}, @emph{symbol}, @emph{number}, @emph{char} (or @emph{character}), @emph{string}, @emph{vector}, @emph{port}, and @emph{procedure}. The empty list is a special +object of its own type; it satisfies none of the above predicates. + +@vindex symbol? +@vindex pair? +@vindex boolean? +@cindex @w{type} + +@vindex vector? +@vindex string? +@vindex char? +@vindex number? + +@cindex @w{empty list} +@vindex procedure? +@vindex port? + +Although there is a separate boolean type, +any Scheme value can be used as a boolean value for the purpose of a +conditional test. As explained in section @ref{Booleans}, all +values count as true in such a test except for @t{#f}. +@c and possibly the empty list. +@c The only value that is guaranteed to count as +@c false is \schfalse{}. It is explicitly unspecified whether the empty list +@c counts as true or as false. +This report uses the word ``true'' to refer to any +Scheme value except @t{#f}, and the word ``false'' to refer to +@t{#f}. +@cindex @w{false} +@cindex @w{true} + +@node External representations, Storage model, Disjointness of types, Basic concepts +@section External representations + + + +An important concept in Scheme (and Lisp) is that of the @emph{external +representation} of an object as a sequence of characters. For example, +an external representation of the integer 28 is the sequence of +characters ``@t{28}'', and an external representation of a list consisting +of the integers 8 and 13 is the sequence of characters ``@t{(8 13)}''. + +The external representation of an object is not necessarily unique. The +integer 28 also has representations ``@t{#e28.000}'' and ``@t{#x1c}'', and the +list in the previous paragraph also has the representations ``@t{( 08 13 +)}'' and ``@t{(8 .@: (13 .@: ()))}'' (see section @pxref{Pairs and lists}). + +Many objects have standard external representations, but some, such as +procedures, do not have standard representations (although particular +implementations may define representations for them). + +An external representation may be written in a program to obtain the +corresponding object (see @samp{quote}, section @pxref{Literal expressions}). + +External representations can also be used for input and output. The +procedure @samp{read} (section @pxref{Input}) parses external +representations, and the procedure @samp{write} (section @pxref{Output}) +generates them. Together, they provide an elegant and powerful +input/output facility. + +Note that the sequence of characters ``@t{(+ 2 6)}'' is @emph{not} an +external representation of the integer 8, even though it @emph{is} an +expression evaluating to the integer 8; rather, it is an external +representation of a three-element list, the elements of which are the symbol +@t{+} and the integers 2 and 6. Scheme's syntax has the property that +any sequence of characters that is an expression is also the external +representation of some object. This can lead to confusion, since it may +not be obvious out of context whether a given sequence of characters is +intended to denote data or program, but it is also a source of power, +since it facilitates writing programs such as interpreters and +compilers that treat programs as data (or vice versa). + +The syntax of external representations of various kinds of objects +accompanies the description of the primitives for manipulating the +objects in the appropriate sections of chapter @ref{Standard procedures}. + +@node Storage model, Proper tail recursion, External representations, Basic concepts +@section Storage model + + + +Variables and objects such as pairs, vectors, and strings implicitly +denote locations or sequences of locations. A string, for +@cindex @w{location} +example, denotes as many locations as there are characters in the string. +(These locations need not correspond to a full machine word.) A new value may be +stored into one of these locations using the @t{string-set!} procedure, but +the string continues to denote the same locations as before. + +An object fetched from a location, by a variable reference or by +a procedure such as @samp{car}, @samp{vector-ref}, or @samp{string-ref}, is +equivalent in the sense of @code{eqv?} +@c and \ide{eq?} ?? +(section @pxref{Equivalence predicates}) +@vindex @w{eqv?} +to the object last stored in the location before the fetch. + +Every location is marked to show whether it is in use. +No variable or object ever refers to a location that is not in use. +Whenever this report speaks of storage being allocated for a variable +or object, what is meant is that an appropriate number of locations are +chosen from the set of locations that are not in use, and the chosen +locations are marked to indicate that they are now in use before the variable +or object is made to denote them. + +In many systems it is desirable for constants (i.e. the values of +@cindex @w{constant} +literal expressions) to reside in read-only-memory. To express this, it is +convenient to imagine that every object that denotes locations is associated +with a flag telling whether that object is mutable or +@cindex @w{mutable} +immutable. In such systems literal constants and the strings +@cindex @w{immutable} +returned by @code{symbol->string} are immutable objects, while all objects +@vindex @w{symbol->string} +created by the other procedures listed in this report are mutable. It is an +error to attempt to store a new value into a location that is denoted by an +immutable object. + +@node Proper tail recursion, , Storage model, Basic concepts +@section Proper tail recursion + + + +Implementations of Scheme are required to be +@emph{properly tail-recursive}. +@cindex @w{proper tail recursion} +Procedure calls that occur in certain syntactic +contexts defined below are `tail calls'. A Scheme implementation is +properly tail-recursive if it supports an unbounded number of active +tail calls. A call is @emph{active} if the called procedure may still +return. Note that this includes calls that may be returned from either +by the current continuation or by continuations captured earlier by +@samp{call-with-current-continuation} that are later invoked. +In the absence of captured continuations, calls could +return at most once and the active calls would be those that had not +yet returned. +A formal definition of proper tail recursion can be found +in [propertailrecursion]. + + +@quotation +@emph{Rationale:} + +Intuitively, no space is needed for an active tail call because the +continuation that is used in the tail call has the same semantics as the +continuation passed to the procedure containing the call. Although an improper +implementation might use a new continuation in the call, a return +to this new continuation would be followed immediately by a return +to the continuation passed to the procedure. A properly tail-recursive +implementation returns to that continuation directly. + +Proper tail recursion was one of the central ideas in Steele and +Sussman's original version of Scheme. Their first Scheme interpreter +implemented both functions and actors. Control flow was expressed using +actors, which differed from functions in that they passed their results +on to another actor instead of returning to a caller. In the terminology +of this section, each actor finished with a tail call to another actor. + +Steele and Sussman later observed that in their interpreter the code +for dealing with actors was identical to that for functions and thus +there was no need to include both in the language. + +@end quotation + + +A @emph{tail call} is a procedure call that occurs +@cindex @w{tail call} +in a @emph{tail context}. Tail contexts are defined inductively. Note +that a tail context is always determined with respect to a particular lambda +expression. + + + +@itemize @bullet + +@item +The last expression within the body of a lambda expression, +shown as @r{} below, occurs in a tail context. + +@format +@t{(lambda + * * ) +} + +@end format + + + +@item +If one of the following expressions is in a tail context, +then the subexpressions shown as are in a tail context. +These were derived from rules in the grammar given in +chapter @ref{Formal syntax and semantics} by replacing some occurrences of +with . Only those rules that contain tail contexts +are shown here. + + +@format +@t{(if ) +(if ) + +(cond +) +(cond * (else )) + +(case + +) +(case + * + (else )) + +(and * ) +(or * ) + +(let (*) ) +(let (*) ) +(let* (*) ) +(letrec (*) ) + +(let-syntax (*) ) +(letrec-syntax (*) ) + +(begin ) + +(do (*) + ( ) + *) + +@r{where} + + --> ( ) + --> ((*) ) + + --> * + --> * +} + +@end format + + + +@item +If a @samp{cond} expression is in a tail context, and has a clause of +the form @samp{(@r{} => @r{})} +then the (implied) call to +the procedure that results from the evaluation of @r{} is in a +tail context. @r{} itself is not in a tail context. + + +@end itemize + + +Certain built-in procedures are also required to perform tail calls. +The first argument passed to @code{apply} and to +@vindex @w{apply} +@code{call-with-current-continuation}, and the second argument passed to +@vindex @w{call-with-current-continuation} +@code{call-with-values}, must be called via a tail call. +@vindex @w{call-with-values} +Similarly, @code{eval} must evaluate its argument as if it +@vindex @w{eval} +were in tail position within the @code{eval} procedure. +@vindex @w{eval} + +In the following example the only tail call is the call to @samp{f}. +None of the calls to @samp{g} or @samp{h} are tail calls. The reference to +@samp{x} is in a tail context, but it is not a call and thus is not a +tail call. + +@example + +(lambda () + (if (g) + (let ((x (h))) + x) + (and (g) (f)))) + +@end example + + + +@quotation +@emph{Note:} +Implementations are allowed, but not required, to +recognize that some non-tail calls, such as the call to @samp{h} +above, can be evaluated as though they were tail calls. +In the example above, the @samp{let} expression could be compiled +as a tail call to @samp{h}. (The possibility of @samp{h} returning +an unexpected number of values can be ignored, because in that +case the effect of the @samp{let} is explicitly unspecified and +implementation-dependent.) +@end quotation + + + +@c @include{expr} + +@c \vfill\eject +@node Expressions, Program structure, Basic concepts, top +@chapter Expressions + +@menu +* Primitive expression types:: +* Derived expression types:: +* Macros:: +@end menu + + + +@c \newcommand{\syntax}{{\em Syntax: }} +@c \newcommand{\semantics}{{\em Semantics: }} + +@c [Deleted for R5RS because of multiple-value returns. -RK] +@c A Scheme expression is a construct that returns a value, such as a +@c variable reference, literal, procedure call, or conditional. + +Expression types are categorized as @emph{primitive} or @emph{derived}. +Primitive expression types include variables and procedure calls. +Derived expression types are not semantically primitive, but can instead +be defined as macros. +With the exception of @samp{quasiquote}, whose macro definition is complex, +the derived expressions are classified as library features. +Suitable definitions are given in section @ref{Derived expression type}. + +@node Primitive expression types, Derived expression types, Expressions, Expressions +@section Primitive expression types + +@menu +* Variable references:: +* Literal expressions:: +* Procedure calls:: +* Procedures:: +* Conditionals:: +* Assignments:: +@end menu + + + +@node Variable references, Literal expressions, Primitive expression types, Primitive expression types +@subsection Variable references + + + +@deffn {syntax} @r{} + + +An expression consisting of a variable +@cindex @w{variable} +(section @pxref{Variables; syntactic keywords; and regions}) is a variable reference. The value of +the variable reference is the value stored in the location to which the +variable is bound. It is an error to reference an +unbound variable. +@cindex @w{unbound} + + +@format +@t{(define x 28) +x ==> 28 +} +@end format + +@end deffn + +@node Literal expressions, Procedure calls, Variable references, Primitive expression types +@subsection Literal expressions + + + + +@deffn {syntax} quote @r{} + +@deffnx {syntax} @t{'}@r{} + + +@deffnx {syntax} @r{} + + +@samp{(quote @r{})} evaluates to @r{}. +@cindex @w{'} +@r{} +may be any external representation of a Scheme object (see +section @pxref{External representations}). This notation is used to include literal +constants in Scheme code. + + +@format +@t{ +(quote a) ==> a +(quote #(a b c)) ==> #(a b c) +(quote (+ 1 2)) ==> (+ 1 2) +} +@end format + + +@samp{(quote @r{})} may be abbreviated as +@t{'}@r{}. The two notations are equivalent in all +respects. + + +@format +@t{'a ==> a +'#(a b c) ==> #(a b c) +'() ==> () +'(+ 1 2) ==> (+ 1 2) +'(quote a) ==> (quote a) +''a ==> (quote a) +} +@end format + + +Numerical constants, string constants, character constants, and boolean +constants evaluate ``to themselves''; they need not be quoted. + + +@format +@t{'"abc" ==> "abc" +"abc" ==> "abc" +'145932 ==> 145932 +145932 ==> 145932 +'#t ==> #t +#t ==> #t +} +@end format + + +As noted in section @ref{Storage model}, it is an error to alter a constant +(i.e. the value of a literal expression) using a mutation procedure like +@samp{set-car!} or @samp{string-set!}. + +@end deffn + + +@node Procedure calls, Procedures, Literal expressions, Primitive expression types +@subsection Procedure calls + + + +@deffn {syntax} @r{} @r{} @dots{}, + + +A procedure call is written by simply enclosing in parentheses +expressions for the procedure to be called and the arguments to be +passed to it. The operator and operand expressions are evaluated (in an +unspecified order) and the resulting procedure is passed the resulting +arguments. +@cindex @w{procedure call} +@cindex @w{call} + +@format +@t{ +(+ 3 4) ==> 7 +((if #f + *) 3 4) ==> 12 +} +@end format + + +A number of procedures are available as the values of variables in the +initial environment; for example, the addition and multiplication +procedures in the above examples are the values of the variables @samp{+} +and @samp{*}. New procedures are created by evaluating lambda expressions +(see section @pxref{Procedures}). +@ignore todo +At Friedman's request, flushed mention of other ways. +@end ignore + +@c or definitions (see section~\ref{define}). + +Procedure calls may return any number of values (see @code{values} in +@vindex @w{values} +section @pxref{Control features}). With the exception of @samp{values} +the procedures available in the initial environment return one +value or, for procedures such as @samp{apply}, pass on the values returned +by a call to one of their arguments. + +Procedure calls are also called @emph{combinations}. + +@cindex @w{combination} + + +@quotation +@emph{Note:} In contrast to other dialects of Lisp, the order of +evaluation is unspecified, and the operator expression and the operand +expressions are always evaluated with the same evaluation rules. +@end quotation + + + +@quotation +@emph{Note:} +Although the order of evaluation is otherwise unspecified, the effect of +any concurrent evaluation of the operator and operand expressions is +constrained to be consistent with some sequential order of evaluation. +The order of evaluation may be chosen differently for each procedure call. +@end quotation + + + +@quotation +@emph{Note:} In many dialects of Lisp, the empty combination, @t{()}, is a legitimate expression. In Scheme, combinations must have at +least one subexpression, so @t{()} is not a syntactically valid +expression. +@ignore todo +Dybvig: ``it should be obvious from the syntax.'' +@end ignore + +@end quotation + + +@ignore todo +Freeman: +I think an explanation as to why evaluation order is not specified +should be included. It should not include any reference to parallel +evaluation. Does any existing compiler generate better code because +the evaluation order is unspecified? Clinger: yes: T3, MacScheme v2, +probably MIT Scheme and Chez Scheme. But that's not the main reason +for leaving the order unspecified. +@end ignore + + +@end deffn + + +@node Procedures, Conditionals, Procedure calls, Primitive expression types +@subsection Procedures + + + + +@deffn {syntax} lambda @r{} @r{} + +@emph{Syntax:} +@r{} should be a formal arguments list as described below, +and @r{} should be a sequence of one or more expressions. + +@emph{Semantics:} +A lambda expression evaluates to a procedure. The environment in +effect when the lambda expression was evaluated is remembered as part of the +procedure. When the procedure is later called with some actual +arguments, the environment in which the lambda expression was evaluated will +be extended by binding the variables in the formal argument list to +fresh locations, the corresponding actual argument values will be stored +in those locations, and the expressions in the body of the lambda expression +will be evaluated sequentially in the extended environment. +The result(s) of the last expression in the body will be returned as +the result(s) of the procedure call. + + +@format +@t{(lambda (x) (+ x x)) ==> @emph{}a procedure +((lambda (x) (+ x x)) 4) ==> 8 + +(define reverse-subtract + (lambda (x y) (- y x))) +(reverse-subtract 7 10) ==> 3 + +(define add4 + (let ((x 4)) + (lambda (y) (+ x y)))) +(add4 6) ==> 10 +} +@end format + + +@r{} should have one of the following forms: + + + +@itemize @bullet + +@item +@t{(@r{} @dots{},)}: +The procedure takes a fixed number of arguments; when the procedure is +called, the arguments will be stored in the bindings of the +corresponding variables. + +@item +@r{}: +The procedure takes any number of arguments; when the procedure is +called, the sequence of actual arguments is converted into a newly +allocated list, and the list is stored in the binding of the +@r{}. + +@item +@t{(@r{} @dots{}, @r{} @b{.} +@r{})}: +If a space-delimited period precedes the last variable, then +the procedure takes n or more arguments, where n is the +number of formal arguments before the period (there must +be at least one). +The value stored in the binding of the last variable will be a +newly allocated +list of the actual arguments left over after all the other actual +arguments have been matched up against the other formal arguments. + +@end itemize + + +It is an error for a @r{} to appear more than once in +@r{}. + + +@format +@t{((lambda x x) 3 4 5 6) ==> (3 4 5 6) +((lambda (x y . z) z) + 3 4 5 6) ==> (5 6) +} +@end format + + +Each procedure created as the result of evaluating a lambda expression is +(conceptually) tagged +with a storage location, in order to make @code{eqv?} and +@vindex @w{eqv?} +@code{eq?} work on procedures (see section @pxref{Equivalence predicates}). +@vindex @w{eq?} + +@end deffn + + +@node Conditionals, Assignments, Procedures, Primitive expression types +@subsection Conditionals + + + +@deffn {syntax} if @r{} @r{} @r{} +@deffnx {syntax} if @r{} @r{} +@c \/ if hyper = italic + +@emph{Syntax:} +@r{}, @r{}, and @r{} may be arbitrary +expressions. + +@emph{Semantics:} +An @samp{if} expression is evaluated as follows: first, +@r{} is evaluated. If it yields a true value (see +@cindex @w{true} +section @pxref{Booleans}), then @r{} is evaluated and +its value(s) is(are) returned. Otherwise @r{} is evaluated and its +value(s) is(are) returned. If @r{} yields a false value and no +@r{} is specified, then the result of the expression is +unspecified. + + +@format +@t{(if (> 3 2) 'yes 'no) ==> yes +(if (> 2 3) 'yes 'no) ==> no +(if (> 3 2) + (- 3 2) + (+ 3 2)) ==> 1 +} +@end format + + +@end deffn + + +@node Assignments, , Conditionals, Primitive expression types +@subsection Assignments + + + + +@deffn {syntax} set! @r{} @r{} + +@r{} is evaluated, and the resulting value is stored in +the location to which @r{} is bound. @r{} must +be bound either in some region enclosing the @samp{set!} expression +@cindex @w{region} +or at top level. The result of the @samp{set!} expression is +unspecified. + + +@format +@t{(define x 2) +(+ x 1) ==> 3 +(set! x 4) ==> @emph{unspecified} +(+ x 1) ==> 5 +} +@end format + + +@end deffn + + +@node Derived expression types, Macros, Primitive expression types, Expressions +@section Derived expression types + +@menu +* Conditional:: +* Binding constructs:: +* Sequencing:: +* Iteration:: +* Delayed evaluation:: +* Quasiquotation:: +@end menu + + + +The constructs in this section are hygienic, as discussed in +section @ref{Macros}. +For reference purposes, section @ref{Derived expression type} gives macro definitions +that will convert most of the constructs described in this section +into the primitive constructs described in the previous section. + +@ignore todo +Mention that no definition of backquote is provided? +@end ignore + + +@node Conditional, Binding constructs, Derived expression types, Derived expression types +@subsection Conditionals + + + +@deffn {library syntax} cond @dots{}, + +@emph{Syntax:} +Each @r{} should be of the form + +@format +@t{(@r{} @r{} @dots{},) +} +@end format + +where @r{} is any expression. Alternatively, a @r{} may be +of the form + +@format +@t{(@r{} => @r{}) +} +@end format + +The last @r{} may be +an ``else clause,'' which has the form + +@format +@t{(else @r{} @r{} @dots{},)@r{.} +} +@end format + + +@cindex @w{else} + +@cindex @w{=>} + +@emph{Semantics:} +A @samp{cond} expression is evaluated by evaluating the @r{} +expressions of successive @r{}s in order until one of them +evaluates to a true value (see +@cindex @w{true} +section @pxref{Booleans}). When a @r{} evaluates to a true +value, then the remaining @r{}s in its @r{} are +evaluated in order, and the result(s) of the last @r{} in the +@r{} is(are) returned as the result(s) of the entire @samp{cond} +expression. If the selected @r{} contains only the +@r{} and no @r{}s, then the value of the +@r{} is returned as the result. If the selected @r{} uses the +@code{=>} alternate form, then the @r{} is evaluated. +@vindex @w{=>} +Its value must be a procedure that accepts one argument; this procedure is then +called on the value of the @r{} and the value(s) returned by this +procedure is(are) returned by the @samp{cond} expression. +If all @r{}s evaluate +to false values, and there is no else clause, then the result of +the conditional expression is unspecified; if there is an else +clause, then its @r{}s are evaluated, and the value(s) of +the last one is(are) returned. + + +@format +@t{(cond ((> 3 2) 'greater) + ((< 3 2) 'less)) ==> greater + +(cond ((> 3 3) 'greater) + ((< 3 3) 'less) + (else 'equal)) ==> equal + +(cond ((assv 'b '((a 1) (b 2))) => cadr) + (else #f)) ==> 2 +} +@end format + + + +@end deffn + + + +@deffn {library syntax} case @r{} @dots{}, + +@emph{Syntax:} +@r{} may be any expression. Each @r{} should have +the form + +@format +@t{((@r{} @dots{},) @r{} @r{} @dots{},)@r{,} +} +@end format + +where each @r{} is an external representation of some object. +All the @r{}s must be distinct. +The last @r{} may be an ``else clause,'' which has the form + +@format +@t{(else @r{} @r{} @dots{},)@r{.} +} +@end format + + +@vindex else + +@emph{Semantics:} +A @samp{case} expression is evaluated as follows. @r{} is +evaluated and its result is compared against each @r{}. If the +result of evaluating @r{} is equivalent (in the sense of +@samp{eqv?}; see section @pxref{Equivalence predicates}) to a @r{}, then the +expressions in the corresponding @r{} are evaluated from left +to right and the result(s) of the last expression in the @r{} is(are) +returned as the result(s) of the @samp{case} expression. If the result of +evaluating @r{} is different from every @r{}, then if +there is an else clause its expressions are evaluated and the +result(s) of the last is(are) the result(s) of the @samp{case} expression; +otherwise the result of the @samp{case} expression is unspecified. + + +@format +@t{(case (* 2 3) + ((2 3 5 7) 'prime) + ((1 4 6 8 9) 'composite)) ==> composite +(case (car '(c d)) + ((a) 'a) + ((b) 'b)) ==> @emph{unspecified} +(case (car '(c d)) + ((a e i o u) 'vowel) + ((w y) 'semivowel) + (else 'consonant)) ==> consonant +} +@end format + + +@end deffn + + + +@deffn {library syntax} and @dots{}, + +The @r{} expressions are evaluated from left to right, and the +value of the first expression that evaluates to a false value (see +section @pxref{Booleans}) is returned. Any remaining expressions +are not evaluated. If all the expressions evaluate to true values, the +value of the last expression is returned. If there are no expressions +then @t{#t} is returned. + + +@format +@t{(and (= 2 2) (> 2 1)) ==> #t +(and (= 2 2) (< 2 1)) ==> #f +(and 1 2 'c '(f g)) ==> (f g) +(and) ==> #t +} +@end format + + +@end deffn + + + +@deffn {library syntax} or @dots{}, + +The @r{} expressions are evaluated from left to right, and the value of the +first expression that evaluates to a true value (see +section @pxref{Booleans}) is returned. Any remaining expressions +are not evaluated. If all expressions evaluate to false values, the +value of the last expression is returned. If there are no +expressions then @t{#f} is returned. + + +@format +@t{(or (= 2 2) (> 2 1)) ==> #t +(or (= 2 2) (< 2 1)) ==> #t +(or #f #f #f) ==> #f +(or (memq 'b '(a b c)) + (/ 3 0)) ==> (b c) +} +@end format + + +@end deffn + + +@node Binding constructs, Sequencing, Conditional, Derived expression types +@subsection Binding constructs + + +The three binding constructs @samp{let}, @samp{let*}, and @samp{letrec} +give Scheme a block structure, like Algol 60. The syntax of the three +constructs is identical, but they differ in the regions they establish +@cindex @w{region} +for their variable bindings. In a @samp{let} expression, the initial +values are computed before any of the variables become bound; in a +@samp{let*} expression, the bindings and evaluations are performed +sequentially; while in a @samp{letrec} expression, all the bindings are in +effect while their initial values are being computed, thus allowing +mutually recursive definitions. + + +@deffn {library syntax} let @r{} @r{} + +@emph{Syntax:} +@r{} should have the form + +@format +@t{((@r{} @r{}) @dots{},)@r{,} +} +@end format + +where each @r{} is an expression, and @r{} should be a +sequence of one or more expressions. It is +an error for a @r{} to appear more than once in the list of variables +being bound. + +@emph{Semantics:} +The @r{}s are evaluated in the current environment (in some +unspecified order), the @r{}s are bound to fresh locations +holding the results, the @r{} is evaluated in the extended +environment, and the value(s) of the last expression of @r{} +is(are) returned. Each binding of a @r{} has @r{} as its +region. +@cindex @w{region} + + +@format +@t{(let ((x 2) (y 3)) + (* x y)) ==> 6 + +(let ((x 2) (y 3)) + (let ((x 7) + (z (+ x y))) + (* z x))) ==> 35 +} +@end format + + +See also named @samp{let}, section @ref{Iteration}. + +@end deffn + + + +@deffn {library syntax} let* @r{} @r{} + + +@emph{Syntax:} +@r{} should have the form + +@format +@t{((@r{} @r{}) @dots{},)@r{,} +} +@end format + +and @r{} should be a sequence of +one or more expressions. + +@emph{Semantics:} +@samp{Let*} is similar to @samp{let}, but the bindings are performed +sequentially from left to right, and the region of a binding indicated +@cindex @w{region} +by @samp{(@r{} @r{})} is that part of the @samp{let*} +expression to the right of the binding. Thus the second binding is done +in an environment in which the first binding is visible, and so on. + + +@format +@t{(let ((x 2) (y 3)) + (let* ((x 7) + (z (+ x y))) + (* z x))) ==> 70 +} +@end format + + +@end deffn + + + +@deffn {library syntax} letrec @r{} @r{} + +@emph{Syntax:} +@r{} should have the form + +@format +@t{((@r{} @r{}) @dots{},)@r{,} +} +@end format + +and @r{} should be a sequence of +one or more expressions. It is an error for a @r{} to appear more +than once in the list of variables being bound. + +@emph{Semantics:} +The @r{}s are bound to fresh locations holding undefined +values, the @r{}s are evaluated in the resulting environment (in +some unspecified order), each @r{} is assigned to the result +of the corresponding @r{}, the @r{} is evaluated in the +resulting environment, and the value(s) of the last expression in +@r{} is(are) returned. Each binding of a @r{} has the +entire @samp{letrec} expression as its region, making it possible to +@cindex @w{region} +define mutually recursive procedures. + + +@format +@t{(letrec ((even? + (lambda (n) + (if (zero? n) + #t + (odd? (- n 1))))) + (odd? + (lambda (n) + (if (zero? n) + #f + (even? (- n 1)))))) + (even? 88)) + ==> #t +} +@end format + + +One restriction on @samp{letrec} is very important: it must be possible +to evaluate each @r{} without assigning or referring to the value of any +@r{}. If this restriction is violated, then it is an error. The +restriction is necessary because Scheme passes arguments by value rather than by +name. In the most common uses of @samp{letrec}, all the @r{}s are +lambda expressions and the restriction is satisfied automatically. + +@c \todo{use or uses? --- Jinx.} + +@end deffn + + +@node Sequencing, Iteration, Binding constructs, Derived expression types +@subsection Sequencing + + + +@deffn {library syntax} begin @dots{}, + +The @r{}s are evaluated sequentially from left to right, +and the value(s) of the last @r{} is(are) returned. This +expression type is used to sequence side effects such as input and +output. + + +@format +@t{(define x 0) + +(begin (set! x 5) + (+ x 1)) ==> 6 + +(begin (display "4 plus 1 equals ") + (display (+ 4 1))) ==> @emph{unspecified} + @emph{and prints} 4 plus 1 equals 5 +} +@end format + + +@end deffn + + +@node Iteration, Delayed evaluation, Sequencing, Derived expression types +@subsection Iteration + +@c \unsection + + +@noindent + +@deffn {library syntax} do ((@r{} @r{} @r{}) @dots{}) (@r{} @r{} @dots{}) @r{} @dots{} +@cindex @w{do} + +@samp{Do} is an iteration construct. It specifies a set of variables to +be bound, how they are to be initialized at the start, and how they are +to be updated on each iteration. When a termination condition is met, +the loop exits after evaluating the @r{}s. + +@samp{Do} expressions are evaluated as follows: +The @r{} expressions are evaluated (in some unspecified order), +the @r{}s are bound to fresh locations, the results of the +@r{} expressions are stored in the bindings of the +@r{}s, and then the iteration phase begins. + +Each iteration begins by evaluating @r{}; if the result is +false (see section @pxref{Booleans}), then the @r{} +expressions are evaluated in order for effect, the @r{} +expressions are evaluated in some unspecified order, the +@r{}s are bound to fresh locations, the results of the +@r{}s are stored in the bindings of the +@r{}s, and the next iteration begins. + +If @r{} evaluates to a true value, then the +@r{}s are evaluated from left to right and the value(s) of +the last @r{} is(are) returned. If no @r{}s +are present, then the value of the @samp{do} expression is unspecified. + +The region of the binding of a @r{} +@cindex @w{region} +consists of the entire @samp{do} expression except for the @r{}s. +It is an error for a @r{} to appear more than once in the +list of @samp{do} variables. + +A @r{} may be omitted, in which case the effect is the +same as if @samp{(@r{} @r{} @r{})} had +been written instead of @samp{(@r{} @r{})}. + + +@format +@t{(do ((vec (make-vector 5)) + (i 0 (+ i 1))) + ((= i 5) vec) + (vector-set! vec i i)) ==> #(0 1 2 3 4) + +(let ((x '(1 3 5 7 9))) + (do ((x x (cdr x)) + (sum 0 (+ sum (car x)))) + ((null? x) sum))) ==> 25 +} +@end format + + +@c \end{entry} +@end deffn + + +@deffn {library syntax} let @r{} @r{} @r{} + + +``Named @samp{let}'' is a variant on the syntax of @code{let} which provides +@vindex @w{let} +a more general looping construct than @samp{do} and may also be used to express +recursions. +It has the same syntax and semantics as ordinary @samp{let} +except that @r{} is bound within @r{} to a procedure +whose formal arguments are the bound variables and whose body is +@r{}. Thus the execution of @r{} may be repeated by +invoking the procedure named by @r{}. + +@c | <-- right margin + +@format +@t{(let loop ((numbers '(3 -2 1 6 -5)) + (nonneg '()) + (neg '())) + (cond ((null? numbers) (list nonneg neg)) + ((>= (car numbers) 0) + (loop (cdr numbers) + (cons (car numbers) nonneg) + neg)) + ((< (car numbers) 0) + (loop (cdr numbers) + nonneg + (cons (car numbers) neg))))) + ==> ((6 1 3) (-5 -2)) +} +@end format + + +@end deffn + + +@node Delayed evaluation, Quasiquotation, Iteration, Derived expression types +@subsection Delayed evaluation + + + +@deffn {library syntax} delay @r{} + +@ignore todo +Fix. +@end ignore + + +The @samp{delay} construct is used together with the procedure @code{force} to +@vindex @w{force} +implement @dfn{lazy evaluation} or @dfn{call by need}. +@cindex @w{call by need} +@cindex @w{lazy evaluation} +@t{(delay @r{})} returns an object called a +@dfn{promise} which at some point in the future may be asked (by +@cindex @w{promise} +the @samp{force} procedure) +@ignore todo +Bartley's white lie; OK? +@end ignore + to evaluate +@r{}, and deliver the resulting value. +The effect of @r{} returning multiple values +is unspecified. + +See the description of @samp{force} (section @pxref{Control features}) for a +more complete description of @samp{delay}. + +@end deffn + + +@node Quasiquotation, , Delayed evaluation, Derived expression types +@subsection Quasiquotation + + + + +@deffn {syntax} quasiquote @r{} + +@deffnx {syntax} @t{`}@r{} + + +``Backquote'' or ``quasiquote'' expressions are useful +@cindex @w{backquote} +for constructing a list or vector structure when most but not all of the +desired structure is known in advance. If no +commas appear within the @r{}, the result of +@cindex @w{comma} +evaluating +@t{`}@r{} is equivalent to the result of evaluating +@t{'}@r{}. If a comma appears within the +@cindex @w{,} +@r{}, however, the expression following the comma is +evaluated (``unquoted'') and its result is inserted into the structure +instead of the comma and the expression. If a comma appears followed +immediately by an at-sign (@@), then the following +@cindex @w{,@@} +expression must evaluate to a list; the opening and closing parentheses +of the list are then ``stripped away'' and the elements of the list are +inserted in place of the comma at-sign expression sequence. A comma +at-sign should only appear within a list or vector @r{}. + +@c struck: "(in the sense of {\cf equal?})" after "equivalent" + + +@format +@t{`(list ,(+ 1 2) 4) ==> (list 3 4) +(let ((name 'a)) `(list ,name ',name)) + ==> (list a (quote a)) +`(a ,(+ 1 2) ,@@(map abs '(4 -5 6)) b) + ==> (a 3 4 5 6 b) +`((@samp{foo} ,(- 10 3)) ,@@(cdr '(c)) . ,(car '(cons))) + ==> ((foo 7) . cons) +`#(10 5 ,(sqrt 4) ,@@(map sqrt '(16 9)) 8) + ==> #(10 5 2 4 3 8) +} +@end format + + +Quasiquote forms may be nested. Substitutions are made only for +unquoted components appearing at the same nesting level +as the outermost backquote. The nesting level increases by one inside +each successive quasiquotation, and decreases by one inside each +unquotation. + + +@format +@t{`(a `(b ,(+ 1 2) ,(foo ,(+ 1 3) d) e) f) + ==> (a `(b ,(+ 1 2) ,(foo 4 d) e) f) +(let ((name1 'x) + (name2 'y)) + `(a `(b ,,name1 ,',name2 d) e)) + ==> (a `(b ,x ,'y d) e) +} +@end format + + +The two notations + @t{`}@r{} and @t{(quasiquote @r{})} + are identical in all respects. + @samp{,@r{}} is identical to @samp{(unquote @r{})}, + and + @samp{,@@@r{}} is identical to @samp{(unquote-splicing @r{})}. +The external syntax generated by @code{write} for two-element lists whose +@vindex @w{write} +car is one of these symbols may vary between implementations. + +@cindex @w{`} + + +@format +@t{(quasiquote (list (unquote (+ 1 2)) 4)) + ==> (list 3 4) +'(quasiquote (list (unquote (+ 1 2)) 4)) + ==> `(list ,(+ 1 2) 4) + @emph{}i.e., (quasiquote (list (unquote (+ 1 2)) 4)) +} +@end format + + +Unpredictable behavior can result if any of the symbols +@code{quasiquote}, @code{unquote}, or @code{unquote-splicing} appear in +@vindex @w{unquote-splicing} +@vindex @w{unquote} +@vindex @w{quasiquote} +positions within a @r{} otherwise than as described above. + +@end deffn + +@node Macros, , Derived expression types, Expressions +@section Macros + +@menu +* Binding constructs for syntactic keywords:: +* Pattern language:: +@end menu + + + +Scheme programs can define and use new derived expression types, + called @emph{macros}. +@cindex @w{macro} +Program-defined expression types have the syntax + +@example + +(@r{} @r{} ...) + +@end example + +where @r{} is an identifier that uniquely determines the +expression type. This identifier is called the @emph{syntactic +keyword}, or simply @emph{keyword}, of the macro. The +@cindex @w{macro keyword} +@cindex @w{keyword} +@cindex @w{syntactic keyword} +number of the @r{}s, and their syntax, depends on the +expression type. + +Each instance of a macro is called a @emph{use} +@cindex @w{macro use} +of the macro. +The set of rules that specifies +how a use of a macro is transcribed into a more primitive expression +is called the @emph{transformer} +@cindex @w{macro transformer} +of the macro. + +The macro definition facility consists of two parts: + + + +@itemize @bullet + +@item +A set of expressions used to establish that certain identifiers +are macro keywords, associate them with macro transformers, and control +the scope within which a macro is defined, and + +@item +a pattern language for specifying macro transformers. + +@end itemize + + +The syntactic keyword of a macro may shadow variable bindings, and local +variable bindings may shadow keyword bindings. All macros +@cindex @w{keyword} +defined using the pattern language are ``hygienic'' and ``referentially +transparent'' and thus preserve Scheme's lexical scoping [Kohlbecker86], [ +hygienic], [Bawden88], [macrosthatwork], [syntacticabstraction]: + +@cindex @w{hygienic} + +@cindex @w{referentially transparent} + + + + +@itemize @bullet + + +@item +If a macro transformer inserts a binding for an identifier +(variable or keyword), the identifier will in effect be renamed +throughout its scope to avoid conflicts with other identifiers. +Note that a @code{define} at top level may or may not introduce a binding; +see section @ref{Definitions}. + +@item +If a macro transformer inserts a free reference to an +identifier, the reference refers to the binding that was visible +where the transformer was specified, regardless of any local +bindings that may surround the use of the macro. + + +@end itemize + +@vindex @w{define} + +@c The low-level facility permits non-hygienic macros to be written, +@c and may be used to implement the high-level pattern language. + +@c The fourth section describes some features that would make the +@c low-level macro facility easier to use directly. + +@node Binding constructs for syntactic keywords, Pattern language, Macros, Macros +@subsection Binding constructs for syntactic keywords + + + +@samp{Let-syntax} and @samp{letrec-syntax} are +analogous to @samp{let} and @samp{letrec}, but they bind +syntactic keywords to macro transformers instead of binding variables +to locations that contain values. Syntactic keywords may also be +bound at top level; see section @ref{Syntax definitions}. + + +@deffn {syntax} let-syntax @r{} @r{} + +@emph{Syntax:} +@r{} should have the form + +@format +@t{((@r{} @r{}) @dots{},) +} +@end format + +Each @r{} is an identifier, +each @r{} is an instance of @samp{syntax-rules}, and +@r{} should be a sequence of one or more expressions. It is an error +for a @r{} to appear more than once in the list of keywords +being bound. + +@emph{Semantics:} +The @r{} is expanded in the syntactic environment +obtained by extending the syntactic environment of the +@samp{let-syntax} expression with macros whose keywords are +the @r{}s, bound to the specified transformers. +Each binding of a @r{} has @r{} as its region. + + +@format +@t{(let-syntax ((when (syntax-rules () + ((when test stmt1 stmt2 ...) + (if test + (begin stmt1 + stmt2 ...)))))) + (let ((if #t)) + (when if (set! if 'now)) + if)) ==> now + +(let ((x 'outer)) + (let-syntax ((m (syntax-rules () ((m) x)))) + (let ((x 'inner)) + (m)))) ==> outer +} +@end format + + +@end deffn + + +@deffn {syntax} letrec-syntax @r{} @r{} + +@emph{Syntax:} +Same as for @samp{let-syntax}. + +@emph{Semantics:} + The @r{} is expanded in the syntactic environment obtained by +extending the syntactic environment of the @samp{letrec-syntax} +expression with macros whose keywords are the +@r{}s, bound to the specified transformers. +Each binding of a @r{} has the @r{} +as well as the @r{} within its region, +so the transformers can +transcribe expressions into uses of the macros +introduced by the @samp{letrec-syntax} expression. + + +@format +@t{(letrec-syntax + ((my-or (syntax-rules () + ((my-or) #f) + ((my-or e) e) + ((my-or e1 e2 ...) + (let ((temp e1)) + (if temp + temp + (my-or e2 ...))))))) + (let ((x #f) + (y 7) + (temp 8) + (let odd?) + (if even?)) + (my-or x + (let temp) + (if y) + y))) ==> 7 +} +@end format + + +@end deffn + +@node Pattern language, , Binding constructs for syntactic keywords, Macros +@subsection Pattern language + + + +A @r{} has the following form: + + +@deffn {} syntax-rules @r{} @r{} @dots{}, + +@emph{Syntax:} +@r{} is a list of identifiers and each @r{} +should be of the form + +@format +@t{(@r{} @r{