Browse Source

2.5 generic operations

jordyn 4 years ago
parent
commit
915932783c
3 changed files with 399 additions and 0 deletions
  1. 266 0
      2/5/jord/lecture.org
  2. 0 0
      2/5/jord/note
  3. 133 0
      2/5/jord/notes.org

+ 266 - 0
2/5/jord/lecture.org

@@ -0,0 +1,266 @@
+* Lecture 4B: Generic operators
+
+so far we've been thinking about horizontal data abstractions
+
+:       use
+: ================
+:  representation
+
+this is a powerful technique but it's not sufficient for very complex
+systems. 
+
+the problem is that 'george' and 'martha' might both be designing
+representations that are incompatible.
+
+we would like to support multiple representations while still not
+worrying about them from above the abstraction barrier.
+
+we would like to be able to add new things with minimal changes.
+
+we _will_ be doing the complex number system (from the book)
+
+
+
+say we have some selectors and constructors,
+
+: (real-part z)
+: (imag-part z)
+: (magnitude z)
+: (angle z)
+
+: (make-rectangular x y)
+: (make-polar r a)
+
+and we can easily implement some arithmetic:
+
+#+BEGIN_SRC scheme
+  (define (+c z1 z2)
+    (make-rectangular
+     (+ (real-part z1) (real-part z2))
+     (+ (imag-part z1) (imag-part z2))))
+  (define (*c z1 z2)
+    (make-polar
+     (* (magnitude z1) (magnitude z2))
+     (+ (angle z1) (angle z2))))
+  ;; etc...
+#+END_SRC
+
+now we can ask 'george to build a representation:
+
+#+BEGIN_SRC scheme
+  (define (make-rectangular x y)
+    (cons x y))
+  (define (real-part z) (car z))
+  (define (imag-part z) (cdr z))
+
+  (define (make-polar r a)
+    (cons (* r (cos a)) (* r (sin a))))
+  (define (magnitude z)
+    (sqrt (+ (square (car z))
+	     (square (cdr z)))))
+  (define (angle z)
+    (atan (cdr z) (car z)))
+#+END_SRC
+
+'martha' is going to take a different approach. she will define a pair
+as a mag and angle, not rect form.
+
+which is better? depends. but really: we can't decide.
+
+what we would like is a system that has operations that add, sub, ...,
+and it does not matter that there are two impls floating around.
+
+how do we do this? harry says it's obvious. give em labels.
+
+"designer data" comes with a tag -- gucci numbers
+
+                  -TYPED DATA-
+
+#+BEGIN_SRC scheme
+  (define (attach-type contents)
+    (cons type contents))
+  (define (type datum)
+    (car datum))
+  (define (contents datum)
+    (cdr datum))
+
+  (define (rectangular? z)
+    (eq? (type z) 'rectangular))
+  (define (polar? z)
+    (eq? (type z) 'polar))
+#+END_SRC
+
+here are the edits to george's rect package:
+
+#+BEGIN_SRC scheme
+  (define (make-rectangular x y)
+    (attach-type 'rectangular (cons x y)))
+  (define (real-part-rectangular z)
+    (car z))
+  (define (real-part-rectangular z)
+    (cdr z))
+  ;; etc...
+  (define (make-polar r a)
+    (attach-type 'polar (cons r a)))
+  ;; etc...
+#+END_SRC
+
+generic selectors:
+
+#+BEGIN_SRC scheme
+  (define (real-part z)
+    (cond ((rectangular? z)
+	   (real-part-rectangular
+	    (contents z)))
+	  ((polar? z)
+	   (real-part-polar
+	    (contents z)))))
+#+END_SRC
+
+--> break
+
+this strategy is called "dispatch on type"
+
+the "manager" looks at the type on the data and dispatches it
+accordingly.
+
+what can we criticize?
+  - we had to rename the procedures
+  - what happens when u bring someone new into the system
+    - manager has to add a test to each dispatch procedure
+      (inflexible!)
+    - the manager isn't doing anything
+      - its just a "paper pusher"
+
+abstractly in the system, there's a table
+
+|           | polar           | rect           |
+|-----------+-----------------+----------------|
+| real-part | real-part-polar | real-part-rect |
+| imag-part |                 |                |
+| magnitude | magnitude-polar | magnitude-rect |
+| angle     |                 |                |
+
+the manager is just acting as this table, so let's get rid of it
+
+assume we have a data structure that is a table with ways of
+interacting
+
+: (put key1 key2 value)
+: (get key1 key2)
+
+to install operations in the table:
+
+#+BEGIN_SRC scheme
+  ;; george:
+  (put 'rectangular 'real-part
+       real-part-rectangular)
+  (put 'rectangular 'magnitude
+       magnitude-rectangular)
+  ;; martha:
+  (put 'polar 'real-part real-part-polar)
+  (put 'polar 'magnitude magnitude-polar)
+#+END_SRC
+
+manager has been automated away, replaced by the procedure operate:
+
+#+BEGIN_SRC scheme
+  (define (operate op obj)
+    (let ((proc (get (type obj) op)))
+      (if (not (null? proc))
+	  (proc (contents obj))
+	  (error "undefined operator"))))
+#+END_SRC
+
+to use it:
+
+#+BEGIN_SRC scheme
+  (define (real-part obj)
+    (operate 'real-part obj))
+  (define (magnitude obj)
+    (operate 'magnitude obj))
+#+END_SRC
+
+if z is polar:
+: (real-part z)
+: (operate 'real-part z)
+: ((get 'polar 'real-part) (contents z))
+: (real-part-polar '(1 2))
+
+this is called DATA DIRECTED PROGRAMMING
+
+--> break
+
+the power of this comes when we embed it in a more complex system
+
+:         add  sub  mul  div
+: ---------------------------------------
+: rational |    complex   | ordinary nums
+:  +rat    |     +c -c    |   +  -
+:  *rat    |     *c /c    |   *  /
+:   ...    +------+-------+
+:          | rect | polar |
+
+
+how do we add our old rat system to the generic arith system?
+
+#+BEGIN_SRC scheme
+  (define (make-rat x y)
+    (attach-type 'rational (cons x y)))
+  (put 'rational 'add +rat)
+  (put 'rational 'mul *rat)
+#+END_SRC
+
+to implement the generic add that works with all our types:
+
+#+BEGIN_SRC scheme
+  (define (add x y)
+    (operate-2 'add x y))
+#+END_SRC
+
+to install complex numbers:
+
+#+BEGIN_SRC scheme
+  (define (make-complex z)
+    (attach-type 'complex z))
+  (define (+complex z1 z2)
+    (make-complex (+c z1 z2)))
+  (put 'complex 'add +complex)
+#+END_SRC
+
+to install ordinary numbers:
+
+#+BEGIN_SRC scheme
+  (define (make-number n)
+    (attach-type 'number n))
+  (define (+number x y)
+    (make-number (+ x y)))
+  (put 'number 'add +number)
+#+END_SRC
+
+what if we want to add polynomials?
+
+: x^15 + 2x^7 + 5
+
+: (polynomial x <term-list>)
+
+: ((15 1) (7 2) (0 5))
+
+#+BEGIN_SRC scheme
+  (define (make-poly var term-list)
+    (attach-type 'poly (cons var term-list)))
+  (define (+poly p1 p2)
+    (if (same-var? (var p1) (var p2))
+	(make-poly
+	 (var p1)
+	 (+terms (term-list p1)
+		 (term-list p2)))
+	(error "polys not in same var")))
+  (put 'poly 'add +poly)
+#+END_SRC
+
+we fired the managers
+
+we have DECENTRALIZED CONTROL
+we have DECENTRALIZED CONTROL
+we have DECENTRALIZED CONTROL

+ 0 - 0
2/5/jord/note


+ 133 - 0
2/5/jord/notes.org

@@ -0,0 +1,133 @@
+* 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