summaryrefslogtreecommitdiff
path: root/coding-exercises/3/1.rkt
blob: 4299e9dfd7a116b588ec3185e0c4a56155005399 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#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)