【SICP练习】98 练习2.73

练习2.73

a小题,这是由于Scheme对数字、变量的直接规定,前者会被当作数值类型,后者则会被当作符号类型。因此没必要将这两个谓词添加到数据导向分派中了。如果给数值类型或者符号类型加上一个标志,在get的过程中,又对已知的类型做判断,岂不是在浪费空间和时间。
b小题,我们根据书中已有的范例来完成这道题,也即是第123页最下面到第125页最上面的内容。

(define (install-sum-package)
  (define (addend s) (car s))
       (define (augend s) (cadr s))
       (define (make-sum x y)
          (cons ((=number? x 0) y)
 ((=number? y 0) x)
                ((and (number? x) (number? y))
                 (+ x y))
               (else
                 (attach 'add x y))))
      (put 'addend 'add addend)
      (put 'augend 'add augend)
      (put 'make-sum 'add make-sum)
  (put 'deriv 'add
           (lambda (exp var)
               (make-sum (deriv (addend exp) var)
                   (deriv (augend exp) var))))
      'done)
;Value: install-sum-package
(define (make-sum x y)
  ((get 'make-sum 'add) x y))
;Value: make-sum
(define (addend sum)
  ((get 'addend 'add) (contents sum)))
;Value: addend
(define (augend sum)
  ((get 'augend 'add) (contents sum)))
;Value: augend
(install-sum-package)
;Unbound variable: put
;To continue, call RESTART with an option number:
; (RESTART 8) => Specify a value to use instead of put.
; (RESTART 7) => Define put to a given value.
; (RESTART 6) => Return to read-eval-print level 6.
; (RESTART 5) => Return to read-eval-print level 5.
; (RESTART 4) => Return to read-eval-print level 4.
; (RESTART 3) => Return to read-eval-print level 3.
; (RESTART 2) => Return to read-eval-print level 2.
; (RESTART 1) => Return to read-eval-print level 1.
;Start debugger? (y or n): n

直到写到了这一步,我才发现put没有定义并且不会定义。因此这道题,我曾搁置下来直到通过后面的学习写出了put和get。

(define operation-table (make-table))
(define put (operation-table ‘insert-proc!))
(define get (operation-table ‘lookup-proc))

其中的put中的insert-proc加上一个感叹号,是因为Scheme中的规范——对有破坏性的操作加上”!”。而make-table则在书上第186页及187页有定义,没有学过不要紧,这里就再来用一次传说中的按愿望思维。
b小题中还要求我们写出关于积式的求导过程,然后也要安装到表格之中。

(define (install-product-package)
    (define (multiplier p) (car p))
    (define (multiplicand p) (cadr p))
    (define (make-product x y)
        (cond ((or (=number? x 0) (=number? y 0)) 0)
               ((=number? x 1) y)
               ((=number? y 1) x)
               ((and (number? x) (number? y))
                (* x y))
               (else
                (attach-tag ‘mul x y))))
      (put ‘multiplier ‘mul multiplier)
      (put ‘multiplicand ‘mul multiplicand)
      (put ‘make-product ‘mul make-product)
          (put ‘deriv ‘mul 
              (lambda (exp var)
                  (make-sum (make-product (multiplier exp)
                                            (deriv (multiplicand exp) var))
                              (make-product (deriv (multiplier exp) var)
                                             (multiplicand exp)))))
          ‘done)
     (define (make-product x y)
         ((get ‘make-product ‘mul) x y))
     (define (multiplier product)
          ((get ‘multiplier ‘mul) (contents product)))
       (define (multiplicand product)
           ((get ‘multiplicand ‘*) (contents product)))

注意之前的attach-tag在这里并不适用,因为其要传入的参数除了一个操作符之外有两个操作对象而不再是一个。

(define (attach-tag type-tag x y)
(list type-tag x y))
(define (type-tag datumn)
(car datumn))
(define (type-tag datumn)
(cdr datumn))

这真是一道漫长的题目哎,c小题参照前面两段代码写起来应该很容易的,如果不知道怎么做乘幂的这个算法,在练习2.56中我们已经遇到过了。
最后一题呢,题目给出了另一种的get形式,但是已经写好的包就不必再加以修改了,因为直接改put即可了。而get中所修改的也只是顺序罢了。因此put的改法也只是改改顺序。

(put ‘make-sumadd make-sum)
(putadd ‘make-sum make-sum)

前面一个是之前写好的,后面一个是这个小题中改过之后的。



感谢访问,希望对您有所帮助。 欢迎关注或收藏、评论或点赞。


为使本文得到斧正和提问,转载请注明出处:
http://blog.csdn.net/nomasp


版权声明:本文为 NoMasp柯于旺 原创文章,如需转载请联系本人。

posted @ 2015-03-06 12:16  nomasp  阅读(165)  评论(0编辑  收藏  举报