莊周夢蝶

          生活、程序、未來
             :: 首頁 ::  ::  :: 聚合  :: 管理

          sicp 習題3.6-3.8試解

          Posted on 2007-08-01 15:45 dennis 閱讀(404) 評論(0)  編輯  收藏 所屬分類: 計算機科學與基礎
          習題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)執行的順序不同時,返回的值不同。


          主站蜘蛛池模板: 平乡县| 行唐县| 邹城市| 西峡县| 睢宁县| 沿河| 垫江县| 克什克腾旗| 二连浩特市| 封丘县| 红桥区| 贺州市| 奇台县| 灵石县| 阳谷县| 福建省| 双流县| 平原县| 黄浦区| 商河县| 济阳县| 遂平县| 丰城市| 尤溪县| 井陉县| 大渡口区| 社旗县| 扎囊县| 大冶市| 乌鲁木齐市| 金寨县| 华坪县| 无极县| 招远市| 红河县| 正定县| 麟游县| 永靖县| 济宁市| 大港区| 曲沃县|