summaryrefslogtreecommitdiff
path: root/coding-exercises/3/7.rkt
blob: b104ad1fb268fb5203cad037a1f3da78ab240fab (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
72
73
#lang racket
;; 7
;; import from 1.rkt
(define (make-accumulator amount)
  (lambda (add-this)
    (set! amount (+ amount add-this))
    amount))

(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))

(define (make-account balance secret)
  (define secrets (list secret))

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

  (define (args->dispatch fn)
    (lambda (arg-list)
      (let ((password (car arg-list))
            (m (cadr arg-list)))
        (if (memq password secrets)
          (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 (make-joint account password new-password)
  ((account password 'new-password) new-password))

(define paul-acc (make-account 100 'open-sesame))
((paul-acc 'open-sesame 'withdraw) 10)
(make-joint paul-acc 'open-sesame 'rosebud)
((paul-acc 'rosebud 'withdraw) 10)

;; 8
(define hidden '())
(define (f v)
  (if (null? hidden)
    (begin
      (set! hidden v)
      hidden)
    0))
(+ (f 0) (f 0))