This Assignment, should you choose to accept it, is to: (a) hack on the "differentiation" code from the lecture. First, add the following unary functions to the code: sin cos exp log (natural log); add the following binary functions: expt. Second, get it to produce better output, where "better" means not having things like "(+ 2 2)" in the output. Don't let the perfect be the enemy of the good, because doing this perfectly is very hard. Just try to do as good a job as seems reasonable. Third, clean up the code as much as you can by abstracting out repeated code. Such as "multiplication by the derivative of the argument." Fourth, figure out a way to set up a test suite and automate the process of checking all the tests and saying which failed. Be careful about floating point inaccuracy: (expt (sqrt 2) 2) evaluated to 2.0000000000000004, that is not a bug but just an inevitable result of finite precision. (For clarification: this is a test facility for testing the differentiation stuff.) *** TEST SUITE HINT *** There are many right answers, e.g., (diff '(* (+ x 1) x) 'x) ? (+ (* 1 x) (* (+ x 1) 1)) ? (+ x (* (+ x 1) 1)) ? (+ (* 1 x) (+ x 1)) ? (+ x (+ x 1)) ? (+ (* 1 (+ 1 x)) (* x 1)) ? (+ (* 2 x) 1) ? (+ 1 (* 2 x)) etc If you bake one of these into your test suite, then improving the system to simplify better will break your test suite, which is yuck. The "right" thing to do is to make a test strategy which is robust to this. Here, an easy trick would be to choose a value for x, say 4.237649, and check if evaluating the expression with the given value for x gives the same result as evaluating a "known correct" derivative you've done by hand. If you do this for a couple values of x, and they're always equal (up to floating point issues), you can be quite confident that the case is right. (b) Add a "macro" facility to the meta-circular Scheme evaluator from lecture. Use it to implement "let" and "cond" by expanding such forms into a simple lambda, and a series of nested if's, respectively. For extra credit, implement the "=>" facility of cond (see the Scheme manual for details.) *** TO CLARIFY *** The interpreter currently looks like this: (define my-eval (lambda (expr env) (cond ((number? expr) expr) ; NUMBER ((symbol? expr) ; VARIABLE (lookup expr (append env global-vars))) ((and (pair? expr) (equal? (car expr) 'lambda)) ; (LAMBDA (var...) body) (list 'closure (cadr expr) (caddr expr) env)) ((and (pair? expr) (equal? (car expr) 'quote)) ; (QUOTE something) (cadr expr)) ((and (pair? expr) (equal? (car expr) 'if)) ; (IF test then else) (my-eval ((if (my-eval (cadr expr) env) caddr cadddr) expr) env)) ;; *** Add two new cases here *** ;; *** This implements LET ((and (pair? expr) (equal? (car expr) 'let)) ; (LET ((var val)...) body) (my-eval *TRANSFORMED-EXPRESSION-GOES-HERE* env)) ;; *** This implements COND ((and (pair? expr) (equal? (car expr) 'cond)) ; (COND ((test result)...[(ELSE result)])) (my-eval *TRANSFORMED-EXPRESSION-GOES-HERE* env)) ;; Special forms go above here. ((pair? expr) ; (f arg ...) (my-apply (my-eval (car expr) env) (map (lambda (expr) (my-eval expr env)) (cdr expr)))) ))) There are missing cases for "let" and "cond". Fill them in!