読書会

なかなかリハビリできてない。今日は問題 3.7 で凄いモノを見せて頂きました。

その前に

問題 3.3 ですが、解としては以下になるんかな。

(define (make-account balance password)
  (define (withdraw amount)
    (if (>= balance amount)
        (begin (set! balance (- balance amount))
               balance)
        "Insufficient funds"))
  (define (deposit amount)
    (set! balance (+ balance amount))
    balance)
  (define (dispatch p m)
    (if (eq? p password)
        (cond ((eq? m 'withdraw) withdraw)
              ((eq? m 'deposit) deposit)
              (else
                (error "Unknown request -- MAKE-ACCOUNT" m)))
        "Incorrect password"))
  dispatch)

なんですが、make-joint は直感的に以下なカタチで書けるとの事。

(define (make-joint account p1 p2)
  (let ((withdraw (account p1 'withdraw))
        (diposit (account p1 'deposit)))
    (define (dispatch p m)
      (if (eq? p p2)
          (cond ((eq? m 'withdraw) withdraw)
                ((eq? m 'deposit) deposit)
                (error "Unknown request -- MAKE-JOINT" m))
         "Incorrect password"))
    dispatch))

ただ、これでは問題 3.3 の解にほぼ手が入っていないから微妙との事。あるいは同じ dispatch があるのは微妙との事。最初、その意図を理解しかねていたのですが、同じソレがあるのは確かに微妙だわな。
では dispatch てきな手続きオブジェクトを戻すナニを戻す手続きを定義すりゃ良いんじゃね? と言いってたのですが、それはスルーで以下な手続きが出てきた。

(define (make-account balance password)
  (define (withdraw amount)
    (if (>= balance amount)
        (begin (set! balance (- balance amount))
               balance)
        "Insufficient funds"))
  (define (deposit amount)
    (set! balance (+ balance amount))
    balance)
  (define (dispatch password)
    (lambda (m p)
      (if (eq? p password)
          (cond ((eq? m 'withdraw) withdraw)
                ((eq? m 'deposit) deposit)
	        ((eq? m 'dispatch) dispatch)
                (else
                  (error "Unknown request -- MAKE-ACCOUNT" m)))
          "Incorrect password")))
  (dispatch password))

で、make-joint の定義が以下かな。

(define (make-joint acc p1 p2)
  ((acc 'dispatch p1) p2))

ちょっと試験してませんが、こんなカンジだったと思います。これはなかなか。
dispatch な手続きオブジェクトを戻す手続きを書こうと言う方も微妙ですが、上記な実装もなかなかに変態だ。わははは的。