#lang racket ;;;;;;;;;; ;; 3.38 ;; ;;;;;;;;;; (define (make-account initial-balance) (define balance initial-balance) (define (deposit amount) (set! balance (+ balance amount))) (define (withdraw amount) (set! balance (- balance amount))) (define (halve) (set! balance (/ balance 2))) (define (dispatch m) (cond [(eq? m 'deposit) deposit] [(eq? m 'withdraw) withdraw] [(eq? m 'halve) halve] [(eq? m 'balance) balance] [else (error "Unknown message -- DISPATCH" m)])) dispatch) (define (peter acct) ((acct 'deposit) 10)) (define (paul acct) ((acct 'withdraw) 20)) (define (mary acct) ((acct 'halve))) ;; What are the possible final balances after allowing these three transactions to ;; be completed sequentially in any order? (define (test sequence) (define test-account (make-account 100)) (for ([p sequence]) (p test-account)) (test-account 'balance)) (for/list ([seq (in-permutations (list peter paul mary))]) (test seq)) ;; '(40 50 40 35 45 45) ;; What are some other values that could be produced if the processes could be ;; interleaved? ;; Interleaving the processes allows us to ignore one or two commands because ;; those commands could always be executed between the third command's read and ;; write operations. So one new value would be 110, obtained by the following ;; sequence of events: ;; peter reads balance = 100 ;; peter computes (+ balance 10) and gets 110 ;; paul does his transaction ;; mary does her transaction ;; peter sets balance to 110