diff options
author | Daniel Kraft <d@domob.eu> | 2009-08-27 19:26:04 +0200 |
---|---|---|
committer | Daniel Kraft <d@domob.eu> | 2009-08-27 19:26:04 +0200 |
commit | ff810079188b8d04224959d5b54254d3e142d6c3 (patch) | |
tree | a58a203dd1a4f151ee8730c5a8290b0c36c2a04e /doc/ref/goops-tutorial.texi | |
parent | 9a9f123144c179ef659252d3442117d6b774be7f (diff) | |
parent | fa316af70ff11767d9a8eb971d9e0b888152a15c (diff) | |
download | guile-ff810079188b8d04224959d5b54254d3e142d6c3.tar.gz |
Merge branch 'master' of git://git.savannah.gnu.org/guile into elisp
Diffstat (limited to 'doc/ref/goops-tutorial.texi')
-rw-r--r-- | doc/ref/goops-tutorial.texi | 819 |
1 files changed, 819 insertions, 0 deletions
diff --git a/doc/ref/goops-tutorial.texi b/doc/ref/goops-tutorial.texi new file mode 100644 index 000000000..600be7730 --- /dev/null +++ b/doc/ref/goops-tutorial.texi @@ -0,0 +1,819 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 2008, 2009 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@c Original attribution: + +@c +@c STk Reference manual (Appendix: An Introduction to STklos) +@c +@c Copyright © 1993-1999 Erick Gallesio - I3S-CNRS/ESSI <eg@unice.fr> +@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 section introduces the @goops{} package in more detail. It was +originally written by Erick Gallesio as an appendix for the STk +reference manual, and subsequently adapted to @goops{}. + +The procedures and syntax described in this tutorial are provided by +Guile modules that may need to be imported before being available. +The main @goops{} module is imported by evaluating: + +@lisp +(use-modules (oop goops)) +@end lisp +@findex (oop goops) +@cindex main module +@cindex loading +@cindex preparing + +@menu +* Copyright:: +* Class definition:: +* Instance creation and slot access:: +* Slot description:: +* Inheritance:: +* Generic functions:: +@end menu + +@node Copyright +@subsection Copyright + +Original attribution: + +STk Reference manual (Appendix: An Introduction to STklos) + +Copyright © 1993-1999 Erick Gallesio - I3S-CNRS/ESSI <eg@@unice.fr> +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 author's permission + +@node Class definition +@subsection Class definition + +A new class is defined with the @code{define-class} 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 + +@var{class} is the class being defined. The list of +@var{superclass}es specifies which existing classes, if any, to +inherit slots and properties from. Each @var{slot-description} gives +the name of a slot and optionally some ``properties'' of this slot; +for example its initial value, the name of a function which will +access its value, and so on. Slot descriptions and inheritance are +discussed more below. For class options, see @ref{Class Options}. +@cindex slot + +As an example, let us define a type for representing a complex number +in terms of two real numbers.@footnote{Of course Guile already +provides complex numbers, and @code{<complex>} is in fact a predefined +class in GOOPS; but the definition here is still useful as an +example.} This can be done with the following class definition: + +@lisp +(define-class <my-complex> (<number>) + r i) +@end lisp + +This binds the variable @code{<my-complex>} to a new class whose +instances will contain two slots. These slots are called @code{r} and +@code{i} and will hold the real and imaginary parts of a complex +number. Note that this class inherits from @code{<number>}, which is a +predefined class.@footnote{@code{<number>} is the direct superclass of +the predefined class @code{<complex>}; @code{<complex>} is the +superclass of @code{<real>}, and @code{<real>} is the superclass of +@code{<integer>}.} + +@node Instance creation and slot access +@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 <my-complex>)) +@end lisp + +@noindent +will create a new @code{<my-complex>} 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!} +sets the value of an object slot and @code{slot-ref} retrieves it. + +@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 + +@noindent +Then the expression + +@lisp +(describe c) +@end lisp + +@noindent +will print the following information on the standard output: + +@smalllisp +#<<my-complex> 401d8638> is an instance of class <my-complex> +Slots are: + r = 10 + i = 3 +@end smalllisp + +@node Slot description +@subsection Slot description +@c \label{slot-description} + +When specifying a slot (in a @code{(define-class @dots{})} form), +various options can be specified in addition to the slot's name. Each +option is specified by a keyword. The list of authorized keywords is +given below: + +@cindex keyword +@itemize @bullet +@item +@code{#:init-value} permits to supply a constant default value for the +slot. The value is obtained by evaluating the form given after the +@code{#:init-value} at class definition time. +@cindex default slot value +@findex #:init-value + +@item +@code{#:init-form} specifies a form that, when evaluated, will return +an initial value for the slot. The form is evaluated each time that +an instance of the class is created, in the lexical environment of the +containing @code{define-class} expression. +@cindex default slot value +@findex #:init-form + +@item +@code{#:init-thunk} permits to supply a thunk that will provide a +default value for the slot. The value is obtained by invoking the +thunk at instance creation time. +@findex default slot value +@findex #:init-thunk + +@item +@code{#:init-keyword} permits to specify a keyword for initializing the +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{<my-complex>} class +seen before. A definition could be: + +@lisp +(define-class <my-complex> (<number>) + (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 <my-complex> #:r 1 #:i 2)) +(get-r c1) @result{} 1 +(set-r! c1 12) +(get-r c1) @result{} 12 +(define c2 (make <my-complex> #: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{<my-complex>} class, using the +@code{#:accessor} option, could be: + +@findex set! +@lisp +(define-class <my-complex> (<number>) + (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{<my-complex>} class using virtual slots is +given in Figure@ 2. + +@example +@group +@lisp +(define-class <my-complex> (<number>) + ;; 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{<my-complex>} 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 +@smalllisp +(define c (make <my-complex> #: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) +@print{} +#<<my-complex> 401e9b58> is an instance of class <my-complex> +Slots are: + r = 1 + i = 10 + m = 10.0498756211209 + a = 1.47112767430373 +@end smalllisp +@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 <my-complex> #:r x #:i y))) + +(define make-polar + (lambda (x y) (make <my-complex> #:magn x #:angle y))) +@end lisp + +@node Inheritance +@subsection Inheritance +@c \label{inheritance} + +@menu +* Class hierarchy and inheritance of slots:: +* Class precedence list:: +@end menu + +@node Class hierarchy and inheritance of slots +@subsubsection 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{<object>}, 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{<top>} is also shown; this class is the +super class of all Scheme objects. In particular, @code{<top>} is the +super class of all standard Scheme types. + +@example +@group +@image{hierarchy} +@center @emph{Fig 1: A class hierarchy} +@iftex +@emph{(@code{<complex>} which is the direct subclass of @code{<number>} +and the direct superclass of @code{<real>} 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 Class precedence list +@subsubsection 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 <object> <top>) +@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{} (#<<class> B 401b97c8> + #<<class> <object> 401e4a10> + #<<class> <top> 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 <object> <top>) +@end lisp + +@node Generic functions +@subsection Generic functions + +@menu +* Generic functions and methods:: +* Next-method:: +* Example:: +@end menu + +@node Generic functions and methods +@subsubsection 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 <integer>) b) 'integer) +(define-method (G (a <real>) 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{<top>}. Thus, the first method definition is +equivalent to + +@cindex parameter specializers +@lisp +(define-method (G (a <integer>) (b <top>)) '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 <integer>) (b <number>)) 'integer-number) +(define-method (G (a <integer>) (b <real>)) 'integer-real) +(define-method (G (a <integer>) (b <integer>)) 'integer-integer) +(define-method (G a (b <number>)) '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 +@subsubsection Next-method + +When you call a generic function, with a particular set of arguments, +GOOPS builds a list of all the methods that are applicable to those +arguments and orders them by how closely the method definitions match +the actual argument types. It then calls the method at the top of this +list. If the selected method's code wants to call on to the next method +in this list, it can do so by using @code{next-method}. + +@lisp +(define-method (Test (a <integer>)) (cons 'integer (next-method))) +(define-method (Test (a <number>)) (cons 'number (next-method))) +(define-method (Test a) (list 'top)) +@end lisp + +With these definitions, + +@lisp +(Test 1) @result{} (integer number top) +(Test 1.0) @result{} (number top) +(Test #t) @result{} (top) +@end lisp + +@code{next-method} is always called as just @code{(next-method)}. The +arguments for the next method call are always implicit, and always the +same as for the original method call. + +If you want to call on to a method with the same name but with a +different set of arguments (as you might with overloaded methods in C++, +for example), you do not use @code{next-method}, but instead simply +write the new call as usual: + +@lisp +(define-method (Test (a <number>) min max) + (if (and (>= a min) (<= a max)) + (display "Number is in range\n")) + (Test a)) + +(Test 2 1 10) +@print{} +Number is in range +@result{} +(integer number top) +@end lisp + +(You should be careful in this case that the @code{Test} calls do not +lead to an infinite recursion, but this consideration is just the same +as in Scheme code in general.) + +@node Example +@subsubsection Example + +In this section we shall continue to define operations on the @code{<my-complex>} +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 <my-complex>) (b <my-complex>)) + (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 <my-complex>) (b <my-complex>)) + (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 <real>) (b <real>)) (+ a b)) + + (define-method (new-+ (a <real>) (b <my-complex>)) + (make-rectangular (+ a (real-part b)) (imag-part b))) + + (define-method (new-+ (a <my-complex>) (b <real>)) + (make-rectangular (+ (real-part a) b) (imag-part a))) + + (define-method (new-+ (a <my-complex>) (b <my-complex>)) + (make-rectangular (+ (real-part a) (real-part b)) + (+ (imag-part a) (imag-part b)))) + + (define-method (new-+ (a <number>)) 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 <my-complex>) #t) +(define-method (complex? c) #f) + +(define-method (number? n <number>) #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. + |