**Exercise 2.77**

In order to trace through the procedures called in evaluating the expression *(magnitude z)* we can use the substitution model:

```
(magnitude '(complex rectangular 3 4)) =>
(apply-generic 'magnitude '(complex rectangular 3 4)) =>
(apply magnitude '(rectangular 3 4)) =>
(apply-generic 'magnitude '(rectangular 3 4)) =>
(apply magnitude '(3 4)) =>
5
```

*Apply-generic* is invoked twice – once for each of the tags *complex* and *rectangular*.

The first time *apply-generic* is invoked it strips off the tag *complex* of its argument and passes the rest of the argument to the generic *magnitude* procedure.

Generic *magnitude* invokes *apply-generic* again. This time the tag *rectangular* is stripped from the argument and the rest of it is passed to the internal *magnitude* procedure defined in the *rectangular* package. At this stage the desired computation is finally carried out without further calls to *apply-generic*.

**Exercise 2.78**

Modified definitions of *attach-tag*, *type-tag*, and *contents*:

```
(define (attach-tag type-tag contents)
(if (eq? type-tag 'scheme-number)
contents
(cons type-tag contents)))
(define (type-tag datum)
(cond ((number? datum) 'scheme-number)
((pair? datum) (car datum))
(else (error "Bad tagged datum --TYPE-TAG" datum))))
(define (contents datum)
(cond ((number? datum) datum)
((pair? datum) (cdr datum))
(else (error "Bad tagged datum --TYPE-TAG" datum))))
```

**Exercise 2.79**

Definition of a generic *equ?* predicate:

```
(define (equ? x y) (apply-generic 'equ? x y))
```

Code we need to add to the *scheme-number* package:

```
(put 'equ? '(scheme-number scheme-number)
(lambda (x y) (= x y)))
```

Code we need to add to the *rational* package:

```
(define (equ? x y)
(= (* (numer x)
(denom y))
(* (numer y)
(denom x))))
(put 'equ? '(rational rational) equ?)
```

Code we need to add to the *complex* package:

```
(define (equ? z1 z2)
(and (= (real z1)
(real z2))
(= (imag z1)
(imag z2))))
(put 'equ? '(complex complex) equ?)
```

After these modifications the new operation *equ?* should work for ordinary numbers, rational numbers, and complex numbers.

**Exercise 2.80**

Definition of a generic *=zero?* predicate:

```
(define (=zero? x) (apply-generic '=zero? x))
```

Code we need to add to the *scheme-number* package:

```
(put '=zero? '(scheme-number) (lambda (x) (= x 0)))
```

Code we need to add to the *rational* package:

```
(define (=zero? x)
(= (numer x) 0))
(put '=zero? '(rational) =zero?)
```

Code we need to add to the *complex* package:

```
(define (=zero? z)
(< (mag z) 0.0000001))
(put '=zero? '(complex) =zero?)
```