3.1 Assignment and Local State

set!でデータの中身を変更できるようにすると参照透明性が失なわれてデータの同一性が判断できなくなるよ、というお話(かな?)

3.1

(define (make-accumulator acc)
  (lambda (n)
    (begin
      (set! acc (+ acc n))
      acc)))

3.2

(define (make-monitored proc)
  (let ((calls 0))
    (lambda (m)
      (cond
	((eq? m 'how-many-calls?) calls)
	(else
	  (begin
	    (set! calls (+ calls 1))
	    (proc m))))
      )
    ))

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 (dispatch p m)
    (cond ((not (eq? p password)) (error "Incorrect password"))
	  ((eq? m 'withdraw) withdraw)
	  ((eq? m 'deposit) deposit)
	  (else (error "Unknown request -- MAKE-ACCOUNT"
		       m))))
  dispatch)

3.4

(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 (call-the-cops)
    (display "('ω`)<お客さん、こっち来てもらえますか")
    (newline))
  (let ((times-wrong 0))
    (define (dispatch p m)
      (if (eq? p password)
	(begin
	  (set! times-wrong 0)
	  (cond ((eq? m 'withdraw) withdraw)
		((eq? m 'deposit) deposit)
		(else (error "Unknown request -- MAKE-ACCOUNT"
			     m))))
	(begin
	  (set! times-wrong (+ times-wrong 1))
	  (if (>= times-wrong 7)
	    (call-the-cops)
	    (error "Incorrect password")))))
  dispatch))

ここから3.1.2.
rand-updateは http://www.cs.tau.ac.il/~scheme/mavo-fall-2001/Software/SICP/ch3support.scm で定義されているのを。

3.5

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

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

3.6

(define random-init 100)
(define rand
  (let ((x random-init))
    (lambda (m)
      (cond ((eq? m 'generate)
             (begin (set! x (rand-update x))
                    x))
            ((eq? m 'reset)
             (lambda (new-value)
               (set! x new-value)
               x))
            (else
              (error "Unknown method" m))
            ))))
(rand 'generate) ; => 59
(rand 'generate) ; => 95
(rand 'generate) ; => 51
(rand 'generate) ; => 6
((rand 'reset) 100)
(rand 'generate) ; => 59
(rand 'generate) ; => 95
(rand 'generate) ; => 51
(rand 'generate) ; => 6

3.7

(define (make-joint account password new-password)
  (define (dispatch p m)
    (if (not (eq? p new-password))
      (error "Incorrect password")
      (account password m)))
  dispatch)

3.8

引数の評価順序によって結果の異なる関数適用ができてしまう。

(define f
  (let ((x #f))
    (lambda (n)
      (if x
        x
        (begin (set! x n)
               x)))))