* Lecture 3B Symbolic Differentiation; Quotation
https://youtu.be/bV87UzKMRtE
(alleged) text section 2.2

how to build robust systems:
  insensitive to small changes
  small changes in the problem require small changes in the solution
  instead of solving a problem at every level of the solution,
  solve class of problems, by neighborhoods
  invent a language at that level of detail

therefore,
  small changes take small solutions
  because at each level, there is a language to express alternate
  solutions of the same type

how to use imbeding of languages:

#+BEGIN_SRC scheme
  (define deriv
    (λ (f)
      (λ (x)
	(/ (- (f (+ x dx))
	      (f x))
	   dx))))
#+END_SRC

this deriv is implemented in a specific way, the numerical approx
it takes a procedure and returns as data a procedure

data vs procedure is already confused, but not badly
we want to confuse it very badly

;;;;;;;;;;;;;

derivatives and integrals are inverses of each other
why is it so much easier to take deriv than to find integ?

#+BEGIN_SRC scheme
  (define (deriv exp var)
    (cond ((constant? exp var) 0)
	  ((same-var? exp var) 1)
	  ((sum? exp)
	   (make-sum (deriv (addend exp) var)
		     (deriv (augmend exp) var)))
	  ((product? exp)
	   (make-sum (make-product (m1 exp) (deriv (m2 exp) var))
		     (make-product (deriv (m1 exp) var) (m2 exp))))
	  ;; ...
	  ))
#+END_SRC

gjs: "any time we do anything complicated by recursion we presumably
  need a case analysis. its the essential way to begin"

gjs: its a good idea to define predicates? with a name ending with a ?
  its a conventional interface for humans

there's a lot of wishful thinking here

#+BEGIN_SRC scheme
  (define (constant? exp var)
    (and (atom? exp)
	 (not (eq? exp var))))
  (define (same-var? exp var)
    (and (atom? exp)
	 (eq? exp var)))

  (define (sum? exp)
    (and (not (atom? exp))
	 (eq? (car exp) '+)))

  (define (make-sum a1 a2)
    (list '+ a1 a2))
  (define a1 cadr)
  (define a2 caddr)
  (define (product exp)
    (and (not (atom? exp))
	 (eq? (car exp) '*)))
  (define (make-product m1 m2)
    (list '* m1 m2))
  (define m1 cadr)
  (define m2 caddr)
#+END_SRC

--- break


             deriv rules 
````````````````````````````````````````
 constant?    sum?   a1   a2    ...

 same-var?    make-sum   ...

````````````````````````````````````````
   representation as list structure


clean up the output:
#+BEGIN_SRC scheme
  (define (make-sum a1 a2)
    (cond ((and (number? a1)
		(number? a2))
	   (+ a1 a2))
	  ((and (number? a1) (= a1 0))
	   a2)
	  ((and (number? a2) (= a2 0))
	   a1)
	  (else (list '+ a1 a2))))
#+END_SRC

we've hit a line that gives us tremendous power
we've bought our sledge hammer,,, careful!
