* 2.5 Systems with Generic Operations

:        programs that use numbers
:
: ----------| add sub mul div |------------
:
:        generic arithmetic package
:
: --| add-rat |-+-| add-comp |-+---| + |---
:   | sub-rat | | | sub-comp | |   | - |
:   | mul-rat | | | mul-comp | |   | * |
:   | div-rat | | | div-comp | |   | / |
:               |              |
:    rational   |   complex    |  ordinary
:   arithmetic  |  arithmetic  | arithmetic
:               |------+-------|
:               | rect | polar |
: -----------------------------------------
:
:               list structure &
:         primitive machine arithmetic

** 2.5.1 generic arithmetic operations

#+BEGIN_SRC scheme
  (define (add x y)  (apply-generic 'add x y))
  (define (sub x y)  (apply-generic 'sub x y))
  (define (mul x y)  (apply-generic 'mul x y))
  (define (div x y)  (apply-generic 'div x y))
#+END_SRC

to install the package for ord numbers (get and put are assumed but
not implemented):

#+BEGIN_SRC scheme
  (define (install-scheme-number-package)
    (define (tag x)
      (attach-tag 'scheme-number x))
    (put 'add '(scheme-number scheme-number)
	 (λ (x y) (tag (+ x y))))
    (put 'sub '(scheme-number scheme-number)
	 (λ (x y) (tag (- x y))))
    (put 'mul '(scheme-number scheme-number)
	 (λ (x y) (tag (* x y))))
    (put 'div '(scheme-number scheme-number)
	 (λ (x y) (tag (/ x y))))
    (put 'make 'scheme-number
	 (λ (x) (tag x)))
    'done)
#+END_SRC

users can create ordinary nums with this:

#+BEGIN_SRC scheme
  (define (make-scheme-number n)
    ((get 'make 'scheme-number) n))
#+END_SRC

see book for complete listing of 

install-rational-package
  and
install-complex-package.

** 2.5.2 combining data of different types

how to combine one type with another?

we could add this to the complex package
#+BEGIN_SRC scheme
  (define (add-complex-to-schemenum z x)
    (make-from-real-imag (+ (real-part z) x)
			 (imag-part z)))
  (put 'add '(complex scheme-number)
       (λ (z x) (tag (add-complex-to-schemenum z x))))
#+END_SRC

this is operational but is cumbersome

COERCION

in the general situation of completely unrelated operations acting on
completely unrelated types, implementing explicit cross-type
operations is clumsy but also the only way.

BUT we can do better by doing type coercion

here's one:

#+BEGIN_SRC scheme
  (define (scheme-number->complex n)
    (make-complex-from-real-imag (contents n) 0))
#+END_SRC

these coercions can be logged in one of those tables:

#+BEGIN_SRC scheme
  (put-coercion 'scheme-number 'complex scheme-number->complex)
#+END_SRC

heres an impl:

#+BEGIN_SRC scheme
  (define (apply-generic op . args)
    (let ((type-tags (map type-tag args)))
      (let ((proc (get op type-tags)))
	(if proc
	    (apply proc (map contents args))
	    (if (= (length args 2)
		   (let ((type1 (car type-tags))
			 (type2 (cadr type-tags))
			 (a1 (car args))
			 (a2 (cadr args)))
		     (let ((t1->t2 (get-coercion type1 type2))
			   (t2->t1 (get-coercion type2 type1)))
		       (cond (t1->t2
			      (apply-generic op (t1->t2 a1) a2))
			     (t2->t1
			      (apply-generic op a1 (t2->t1 a2)))
			     (else
			      (error "no method for these types"
				     (list op type-tags))))))
		   (error "no method for these types"
			  (list op type-tags)))))))
#+END_SRC

HIERARCHIES OF TYPES

wow... getting dangerously close to inheritance here

hierarchies can be linear (easier to engineer) or else a tree of types

** 2.5.3 example: symbolic algebra
