天天看點

sicp 習題3.6-3.8試解

習題3.6,我的實作如下:

(define rand

  (let ((x 3))

     (lambda(arg)

      (cond((eq? arg 'generate)

            ((lambda()(set! x (rand-update x)) x)))

           ((eq? arg 'reset)

            (lambda(init) (set! x init) (set! x (rand-update x)) x))

           (else

             error "unkonown op")))))

簡單解釋下,當參數是generate時,直接調用匿名lambda函數(lambda()(set! x (rand-update x)) x) ,最後傳回随機值。而當第一個參數是reset時,傳回匿名函數(lambda(init) (set! x init) (set! x (rand-update x)) x),這個匿名函數接受一個新的初始值,并指派給x,然後調用rand-update

習題3.7,引入指派的代價就是引入了副作用以及相應的複雜性,3.3小節提出了指令式語言與函數式語言的基本差别。這一題,首先修改習題3.3(參見《sicp 3.1小結習題嘗試解答》),增加一個檢查密碼是否正确的功能,用以檢查輸入的原始帳戶密碼是否正确,make-account修改一下

;習題3.3

(define (make-account2 balance passwd)

  (define (checkpwd pwd)

    (eq? pwd passwd))

  (define (withdraw amount)

    (if (>= balance amount)

        (begin (set! balance (- balance amount)) balance)

        "餘額不足"))

  (define (deposit amount)

    (set! balance (+ balance amount))

    balance)

  (define (dispatch pwd m)

    (if (eq? pwd passwd)

        (cond ((eq? m 'withdraw) withdraw)

              ((eq? m 'deposit) deposit)

              ((eq? m 'checkpwd) checkpwd)

            (else

               (error "unknow request--make-account" m)))

        (lambda(x) "incorrect password")))

  dispatch)

那麼,make-joint可以寫為:

(define (make-joint account-name account-pass new-pass)

  (if (account-name 'checkpwd account-pass)

      (lambda (passwd m)

      (if (eq? new-pass passwd)

          (account-name account-pass m)

           (error "incorrect password")))

      (error

         "incorrect password to the original account")))

首先是檢查原始帳戶的密碼是否正确,正确傳回匿名函數(兩個參數passwd m),此匿名函數檢查密碼以及調用原始帳戶操作;如果不正确就提示消息。

測試一下:

> (define dennis-acc (make-account2 100 '123))

> (define zane-acc (make-joint dennis-acc '123 'abc))

> ((dennis-acc '123 'withdraw) 10)

90

>  ((zane-acc 'abc 'withdraw) 10)

80

> 

習題3.8,這一題比較簡單了,在内部維持一個狀态變量即可

(define f

  (let ((y 1))

    (lambda(x) (set! y (* x y)) y)))

測試可知,在(f 1) (f 0)執行的順序不同時,傳回的值不同.

文章轉自莊周夢蝶  ,原文釋出時間 2007-08-01

繼續閱讀