SICP 問題 3.48
;; make-accountの引数にidを追加. ;; dispatchの引数に'numberで口座番号を参照できる. (define (make-account-and-serializer balance id) (define (withdraw amount) (if (>= balance amount) (begin (set! balance (- balance amount)) balance) "Insufficient funds")) (define (deposit amount) (set! balance (+ balance amount)) balance) (let ((balance-serializer (make-serializer))) (define (dispatch m) (cond ((eq? m 'withdraw) withdraw) ((eq? m 'deposit) deposit) ((eq? m 'balance) balance) ((eq? m 'id) id) ((eq? m 'serializer) balance-serializer) (else (error "Unknown request: MAKE-ACCOUNT" m)))) dispatch)) (define (exchange account1 account2) (let ((difference (- (account1 'balance) (account2 'balance)))) ((account1 'withdraw) difference) ((account2 'deposit) difference))) ;; 口座番号の小さいほうから先にserialize. (define (serialized-exchange account1 account2) (let ((id1 (account1 'id)) (id2 (account2 'id))) (let ((smaller (if (< id1 id2) account1 account2)) (bigger (if (< id1 id2)) account2 account1)) (let ((serializer1 (smaller 'serializer)) (serializer2 (bigger 'serializer))) ((serializer2 (serializer1 exchange)) account1 account2)))))
smallerとbiggerへの束縛のいい方法がわからずtwitterで聞いたところ,
t.coR7RS (というか let-values が使える環境) ならこんな感じかなぁ。 (let-values (((x y) (if (< a b) (values a b) (values b a)))) body ...)
— 齊藤敦志 (@SaitoAtsushi) December 6, 2015
と教えていただいたので書き換えました.
二回比較するのが嫌だったんですよね.
;; 口座番号の小さいほうから先にserialize. (use srfi-11) (define (serialized-exchange account1 account2) (let ((id1 (account1 'id)) (id2 (account2 'id))) (let-values (smaller bigger) (if (< id1 id2) (values id1 id2) (values id2 id1)) (let ((serializer1 (smaller 'serializer)) (serializer2 (bigger 'serializer))) ((serializer2 (serializer1 exchange)) account1 account2)))))