Next: , Previous: , Up: Methods and Generic Functions   [Contents][Index]

#### 8.6.5 Generic Function and Method Examples

Consider the following definitions:

```(define-generic G)
(define-method (G (a <integer>) b) 'integer)
(define-method (G (a <real>) b) 'real)
(define-method (G a b) 'top)
```

The `define-generic` call defines G as a generic function. The three next lines define methods for G. Each method uses a sequence of 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 `<top>`. Thus, the first method definition is equivalent to

```(define-method (G (a <integer>) (b <top>)) 'integer)
```

Now, let’s look at some possible calls to the generic function G:

```(G 2 3)    ⇒ integer
(G 2 #t)   ⇒ integer
(G 1.2 'a) ⇒ real
(G #t #f)  ⇒ top
(G 1 2 3)  ⇒ error (since no method exists for 3 parameters)
```

The methods above use only one specializer per parameter list. But in general, any or all of a method’s parameters may be specialized. Suppose we define now:

```(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)
```

With these definitions:

```(G 1 2)   ⇒ integer-integer
(G 1 1.0) ⇒ integer-real
(G 1 #t)  ⇒ integer
(G 'a 1)  ⇒ top-number
```

As a further example 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 complex numbers 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 Figure 8.1.

```(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 8.1: Extending `+` to handle complex numbers

We take advantage here of the fact that generic function are not obliged to have a fixed number of parameters. The four first methods implement 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 (as is also true for the primitive `+`). The last method takes an arbitrary number of parameters33. 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 conclude our implementation (integration?) of complex numbers, we could 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.

#### Footnotes

##### (33)

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

Next: , Previous: , Up: Methods and Generic Functions   [Contents][Index]