#lang racket ;; 1 (define (make-accumulator amount) (lambda (add-this) (set! amount (+ amount add-this)) amount)) (define A (make-accumulator 5)) (A 10) (A 15) (define B (make-accumulator 5)) (B 10) (B 15) ;; 2 (define (make-monitored fn) (define calls (make-accumulator 0)) (lambda (arg-or-message) (cond ((equal? arg-or-message 'how-many-calls?) (calls 0)) ((equal? arg-or-message 'reset-count) (set! calls (make-accumulator 0))) (else (begin (calls 1) (fn arg-or-message)))))) (define s (make-monitored sqrt)) (s 100) (s 'how-many-calls?) ;; 3 (define (make-account balance secret) (define (withdraw amount) (if (>= balance amount) (begin (set! balance (- balance amount)) balance) "Insufficient funds")) (define (deposit amount) (set! balance (+ balance amount)) balance) (define (dispatch m) (cond ((eq? m 'withdraw) withdraw) ((eq? m 'deposit) deposit) (else (error "Unknown request -- MAKE-ACCOUNT" m)))) (define (args->dispatch fn) (lambda (arg-list) (let ((password (car arg-list)) (m (cadr arg-list))) (if (eq? password secret) (fn m) (lambda (a . n) "Wrong password"))))) (define monitored-dispatch (make-monitored (args->dispatch dispatch))) (define (call-the-cops) (lambda (a . n) "Calling the cops")) (define (safe-dispatch . args) (if (> 7 (monitored-dispatch 'how-many-calls?)) (monitored-dispatch args) (call-the-cops))) safe-dispatch) (define acc (make-account 100 'secret-password)) ((acc 'secret-password 'withdraw) 10) ((acc 'some-other-password 'deposit) 50) ((acc 'some-other-password 'deposit) 50) ((acc 'some-other-password 'deposit) 50) ((acc 'some-other-password 'deposit) 50) ((acc 'some-other-password 'deposit) 50) ((acc 'some-other-password 'deposit) 50) ((acc 'some-other-password 'deposit) 50) ((acc 'some-other-password 'deposit) 50)