# 関数型言語の勉強にSICPを読もう - (28) 3章 - 標準部品化力、オブジェクトおよび状態 (127-133ページ)

3章はいよいよ代入とかオブジェクトとかが登場します。

#### 問題3.1

この程度ならスラスラ書けるようになった。

```(define (make-accumulator start)
(lambda (num)
(set! start (+ start num))
start))

(define A (make-accumulator 5))
(define B (make-accumulator 10))
(display (A 3))
(display (B 3))
(display (A 3))```

#### 問題3.2

```(define (make-monitored f)
(let ((counter 0))
(define (dispatch m)
(if (eq? m 'how-many-calls?) counter
(func m)))
(define (func arg)
(set! counter (+ counter 1))
(f arg))
dispatch))

(define s (make-monitored sqrt))

(display (s 100))
(display (s 144))

(display (s 'how-many-calls?))```

#### 問題3.3

```(define (make-account balance password)
(define (dispatch p m)
(if (eq? m 'withdraw) withdraw
(error "unknown op"))
(define (withdraw amount)
(if (>= balance amount)
(begin (set! balance (- balance amount)) balance)
"insufficient funds"))
dispatch)

(define hige-account (make-account 1000000 'hige-pass))

(display ((hige-account 'hige-pass 'withdraw) 450000))

(display ((hige-account 'crack 'withdraw) 450000))```

#### 問題3.4

accountの呼び出しは手続きが返ってくることを期待しているのでエラーも手続きで返そうとか欲張ったら汚くなった。
でも楽しいっす。

```(define (call-the-cops)
(display "help!help"))

(let ((wrong-times 0))
(define (dispatch p m)
(define (error-func arg)
(display "you can not ")
(display m)
(display " ")
(display arg)
(display "\n"))
(begin
(set! wrong-times 0)
(if (eq? m 'withdraw) withdraw
error-func))
(begin
(set! wrong-times (+ 1 wrong-times))
(if (>= wrong-times 7) (begin (call-the-cops) error-func)
error-func))))
(define (withdraw amount)
(if (>= balance amount)
(begin (set! balance (- balance amount)) balance)
"insufficient funds"))
dispatch))

(define hige-account (make-account 1000000 'hige-pass))

(display ((hige-account 'hige-pass 'withdraw) 450000))

((hige-account 'crack1 'withdraw) 450000)
((hige-account 'crack2 'withdraw) 450000)
((hige-account 'crack3 'withdraw) 450000)
((hige-account 'crack4 'withdraw) 450000)
((hige-account 'crack5 'withdraw) 450000)
((hige-account 'crack6 'withdraw) 450000)
((hige-account 'crack7 'withdraw) 450000)```

#### 問題3.5

モンテカルロ積分ですが、思ったよりもとてもシンプルな概念なのでぜひこの問題はチャレンジしてみると面白いと思います。
モンテカルロは並列化できるからうれしいよねと、N氏に教えてもらい納得。

```(use srfi-27)

;; モンテカルロ積分
(define (estimate-integral p x1 y1 x2 y2 trials)
(define (experiment)
(let ((x (random-in-range x1 x2))
(y (random-in-range y1 y2)))
(p x y)))
(let ((s  (* (- y2 y1) (- x2 x1))))
(* s (monte-calro trials experiment))))

(define (random-in-range low high)
(let ((range (- high low)))
(if (<= 1 range)
(random-real)
(+ low (random-integer range)))))

(define (monte-calro 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 (double a)
(* a a))

;; えいっ
(define (unit-circle x y)
(<= (+ (double (- x 0.5)) (double (- y 0.5))) 0.25))
(display (* (estimate-integral unit-circle 0 0 1 1 50000000) 4))```

`3.14176`

でした。

#### 問題3.6

※「SICPを読もう」の目次はこちら

Gerald Jay Sussman Julie Sussman Harold Abelson 和田 英一
ピアソンエデュケーション (2000/02)