In this section we shall continue to define operations on the
<my-complex> class. Suppose that we want to use it to implement
complex numbers completely. For instance a definition for the addition
of two complexes could be
(define-method (new-+ (a <my-complex>) (b <my-complex>))
(make-rectangular (+ (real-part a) (real-part b))
(+ (imag-part a) (imag-part b))))
To be sure that the + used in the method new-+ is the
standard addition we can do:
(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)))))
The define-generic ensures here that new-+ will be defined
in the global environment. Once this is done, we can add methods to the
generic function new-+ which make a closure on the +
symbol. A complete writing of the new-+ methods is shown in
fig:newplus.
(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-+)
Figure 9.1: Extending + to handle complex numbers
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 parameters1. This method acts as a kind of
reduce: it calls the dyadic addition on the car of the
list and on the result of applying it on its rest. To finish, the
set! permits to redefine the + symbol to our extended
addition.
To terminate our implementation (integration?) of complex numbers, we can redefine standard Scheme predicates in the following manner:
(define-method (complex? c <my-complex>) #t)
(define-method (complex? c) #f)
(define-method (number? n <number>) #t)
(define-method (number? n) #f)
...
...
Standard primitives in which complex numbers are involved could also be redefined in the same manner.
[1] The parameter list for
a 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