sicp-ex-2.80

meteorgan

```

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

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

(put '=zero? 'rational-number
(lambda (x) (= (numer x) 0)))

(put '=zero? 'complex-number
(lambda (x) (= (real-part x) (imag-part x) 0)))

```

A type-recursive version

```
;; Version - 1
(define (=zero? data)
(cond
((number? data) (= data 0))
((eq? 'rational (type-tag data))
(=zero? (contents data)))
((eq? 'complex (type-tag data))
(and (=zero? (real-part data))
(=zero? (imag-part data))))
(else (error "xxx"))))

;; Version -2
(define (=zero? data)
(apply-generic '=zero? data))

(define (install-scheme-number-package)
...
(put '=zero? '(scheme-number)
(lambda (x) (= x 0)))) ; scheme-number is the "base-type"

(define (install-rational-number-package)
...
(put '=zero? '(rational)
(lambda (x) (=zero? (numer x) 0)))) ;the numer part might be another type of number, for example a rational number

(define (install-complex-number-package)
...
(put '=zero? '(complex)
(lambda (x)
(and (=zero? (real-part x))  ; ibid
(=zero? (imag-part x)))))) ;ibid
```

Reimu

It's worth noting that defining =zero? in terms of itself as the answer above does, allows for greater flexibility. For instance we can have a rational number whose numer is a complex number. However, I do have slight modification to the answer above:

``` (put '=zero? '(rectangular) (lambda (x) (and (=zero? (real-part x))
(=zero? (imag-part x)))))

(put '=zero? '(polar) (lambda (x) (=zero? (magnitude x))))

(put '=zero? '(complex) =zero?) ;; see ex 2.77. runs apply-generic twice.
```

This approach is more abstract, and is more efficient when dealing with polar numbers as there's no need to convert from one from to the other.