λ3.1節

問題 3.1  問題 3.2  問題 3.3  問題 3.4  問題 3.5 
問題 3.6  問題 3.7  問題 3.8 

問題 3.1
(define (make-accumulator init)
  (let ((sum init))
    (lambda (inc)
       (begin (set! sum (+ sum inc))
              sum))))

(define A (make-accumulator 5))
(A 10)
(A 10)
問題 3.2
(define (make-monitored f)
  (let ((counter 0))
    (lambda (x)
      (if (eq? x 'how-many-calls?) counter
          (begin (set! counter (+ counter 1))
                 (f x))))))
問題 3.3
(define (make-account balance password)
  (define (withdraw amount)
    (if (>= balance amount)
        (begin (set! balance (- balance amount))
               balance)
        "Insufficient funds"))
  (define (deposit amount)
    (set! balance (+ balance amount))
    balance)
  (define (skip amount)
    "Incorrect password")
  (define (dispatch p m)
    (if (eq? p password)
      (cond ((eq? m 'withdraw) withdraw)
            ((eq? m 'deposit) deposit)
            (else (error "Unknown request -- MAKE-ACCOUNT"
                       m)))
      skip))
  dispatch)

(define acc (make-account 100 'secret-password))

((acc 'secret-password 'withdraw) 40) → 60

((acc 'some-other-password 'deposit) 50) → "Incorrect password"
問題 3.4
(define (call-the-cops) "call-the-cops")

(define (make-account balance password)
  (define count 0)
  (define (withdraw amount)
    (set! count 0)
    (if (>= balance amount)
        (begin (set! balance (- balance amount))
               balance)
        "Insufficient funds"))
  (define (deposit amount)
    (set! count 0)
    (set! balance (+ balance amount))
    balance)
  (define (skip amount)
    (set! count (+ count 1))
    (if (>= count 7)
        (call-the-cops)
       "Incorrect password"))
  (define (dispatch p m)
    (if (eq? p password)
      (cond ((eq? m 'withdraw) withdraw)
            ((eq? m 'deposit) deposit)
            (else (error "Unknown request -- MAKE-ACCOUNT"
                       m)))
      skip))
  dispatch)
問題 3.5
(define (square x) (* x x))

(define (estimate-integral P x1 x2 y1 y2 trials)
  (define (test) 
    (P (random-in-range x1 x2) (random-in-range y1 y2)))
  (let ((rsquare (* (- x2 x1) (- y2 y1))))
    (* (monte-carlo trials test) rsquare)))

(define (monte-carlo trials experiment)
  (define (iter trials-remaining trials-passed)
    (cond ((= trials-remaining 0)
           (/ trials-passed trials))
          ((experiment)
           (iter (- trials-remaining 1) (+ trials-passed 1)))
          (else
           (iter (- trials-remaining 1) trials-passed))))
  (iter trials 0))

(define (random-in-range low high)
  (let ((range (- high low)))
    (+ low (random range))))

(estimate-integral 
  (lambda (x y) (<= (+ (square (- x 5)) (square (- y 7))) 9))
  2.0 8.0 4.0 10.0 1000)
問題 3.6
(define rand
  (let ((x random-init))
    (lambda (symbol)
      (cond ((eq? symbol 'generate) (set! x (rand-update x)) x)
            ((eq? symbol 'reset) (lambda (new-value) (set! x new-value) x))
            (else (error "Unknown symbol --- RAND" symbol))))))

問題 3.7
(define (make-account balance password)
  (define new-password 0)
  (define (withdraw amount)
    (if (>= balance amount)
        (begin (set! balance (- balance amount))
               balance)
        "Insufficient funds"))
  (define (deposit amount)
    (set! balance (+ balance amount))
    balance)
  (define (skip amount)
     "Incorrect password")
  (define (joint p)
    (set! new-password p)
    (lambda (p m)
      (if (eq? p new-password)
        (cond ((eq? m 'withdraw) withdraw)
              ((eq? m 'deposit) deposit)
              (else (error "Unknown request -- MAKE-ACCOUNT"
                         m)))
        skip)))
  (define (dispatch p m)
    (if (eq? p password)
      (cond ((eq? m 'withdraw) withdraw)
            ((eq? m 'deposit) deposit)
            ((eq? m 'joint) joint)
            (else (error "Unknown request -- MAKE-ACCOUNT"
                       m)))
      skip))
  dispatch)

(define (make-joint old-acc old-password new-password)
  ((old-acc old-password 'joint) new-password))


(define peter-acc (make-account 100 'open-sesame))

((peter-acc 'open-sesame 'withdraw) 50) → 50

((peter-acc 'rosebud 'deposit) 30) → "Incorrect password"

(define paul-acc (make-joint peter-acc 'open-sesame 'rosebud))

((paul-acc 'rosebud 'deposit) 30) → 80

((paul-acc 'open-sesame 'withdraw) 20) → "Incorrect password"
問題 3.8
(define f
 (let ((x 0))
   (lambda (n)
     (if (= x 0) (begin (set! x 1) n) 0))))

(display (f 0)) (newline)
(display (f 1)) (newline)

(define f
 (let ((x 0))
   (lambda (n)
     (if (= x 0) (begin (set! x 1) n) 0))))

(display (f 1)) (newline)
(display (f 0)) (newline)


または

(define f
  (let ((x 0) (y 0))
    (lambda (z) (set! y x) (set! x z) y)))