; (deriv <expr> <with-respect-to-var>) ==> <new-expr>
; Expr = SimpleExpr | CompoundExpr
; SimpleExpr = number | symbol
; CompoundExpr = pair< (+|*), pair<Expr, pair<Expr, null> >>
; (deriv '(+ x 3) 'x) ; => 1
; (deriv '(+ (* x y) 4) 'x) ; => y
; (deriv '(* x x) 'x) ; => (+ x x)
(define simple-expr? (lambda (e)
(define deriv (lambda (expr var)
(deriv (caddr expr) var))
<handle product expression>
; 1. 可读性差 <- 没有明确的函数名告诉读者每段程序在做什么
; 2. 对新操作的扩展性差 <- 因为目前的代码假设只有两种操作,利用嵌套 if 语句来完成
; 3. 对表达式的表示形式不可变 <- 如果我们要改变表达式的表示形式,比如 '(x + 3),代码将发生巨大改变,因为我们依赖了 list 结构,以及它的选择器, car, cdr, cadr ... 而没有抽象出 Expr 这种抽象数据类型。
(define sum-expr? (lambda (e)
(and (pair? e) (eq? (car e) '+))))
(define variable? (lambda (e)
(and (not (pair? e)) (symbol? e))))
(define make-sum (lambda (e1 e2)
(define addend (lambda (sum) (cadr sum)))
(define augend (lambda (sum) (caddr sum)))
(define deriv (lambda (expr var)
((variable? expr) (if (eq? expr var) 1 0))
(make-sum (deriv (addend expr) var)
(deriv (augend expr) var)))
<handle product expression>)
(error "unknown expression type" expr))
; 此时 (deriv (make-sum 'x 'y) 'x) => '(+ 1 0),但我们希望得到的是约减过的表达式 '1,为了得到后者
(else (list '+ e1 e2)))))