閱讀848 返回首頁    go 技術社區[雲棲]


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

最後更新:2017-05-17 16:01:34

  上一篇:go  一點領悟吧,關於消息傳遞與lambda算子
  下一篇:go  談NullObject模式