Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
59 lines (50 sloc) 2.47 KB

题目 3.41、3.42 是正文make-account的变形。下面先来看下正文中的make-account

(define (make-account balance)
  (define (withdraw amount)
    (if (>= balance amount)
      (begin
        (set! balance (- balance amount))
        balance)
      "Insufficient funds."))
  (define (deposit amount)
    (set! balance (+ balance amount))
    balance)

  (let ((protected (make-serializer)))
    (define (dispatch m)
      (cond
        ((eq? m 'withdraw) (protected withdraw))
        ((eq? m 'deposit) (protected deposit))
        ((eq? m 'balance) balance)
        (else (error "Unknown request -- MAKE-ACCOUNT" m))))
    dispatch))

3.41

这个题修改了dispatch过程中,访问balance时的做法

(define (dispatch m)
  (cond
    ((eq? m 'withdraw) (protected withdraw))
    ((eq? m 'deposit) (protected deposit))
    ((eq? m 'balance) (protected balance)
    (else (error "Unknown request -- MAKE-ACCOUNT" m)))))

这样做的哈,可以避免在执行withdraw或deposit过程中,访问balance的问题,比如withdraw执行过程很长,而这时如果访问balance的值,就会返回withdraw之前的值。

这种情况个人觉得到不会导致账号不一致的情况,因为最终的状态是固定的。

3.42

这个题目从执行效率上来考虑,改成下面的形式

(let ((protected (make-serializer)))
  (let ((protected-withdraw (protected withdraw))
        (protected-deposit (protected deposit)))
    (define (dispatch m)
      (cond
        ((eq? m 'withdraw) protected-withdraw)
        ((eq? m 'deposit) protected-deposit)
        ((eq? m 'balance) balance)
        (else (error "Unknown request -- MAKE-ACCOUNT" m))))
    dispatch))

这相当于把protected-withdraw与protected-deposit给缓存起来了,每次调用(dispatch m)时返回一样的过程,而正文中给出的原有方式,是每次调用相应过程时,都用protected包装下,相当于每次调用都返回一个新过程。

但是,这两种方式是否等价呢?我个人觉得是等价的。

因为make-serializer的功能就是使其作用的过程顺序化,原文给出的方式肯定是顺序化的了,至于本题修改后的方式,其实想想也是顺序化的,因为一旦把某过程作为参数传给make-serializer后,就相当于给该过程加了一个互斥锁,而且该互斥锁是针对方法的,所以修改后的方式也是顺序执行的。