SICPラン③(p26~1.18. 例: ブラックボックス抽象化としての手続き)
作られた手続きは、中身が詳細に知られる必要がない。簡単な例だとニュートン法で用いたsquareで、返り値として引数の二乗がかえってこれば良いのであって、どのように実装されているのかは知る必要がない。ブラックボックスで構わないのである。
そして、一連の手続きのネストを作ると、その他の手続きにおいても同じ名前で使うことができる。(つまりある数の平方根を求める手続き以外でも、improveやgood-enough?などが利用できるようになる。sqrt以外の手続き、いわゆるサブ手続きをsqrt内に局所化することで実現する。これをブロック構造という*1。)
(define (sqrt x) (define (good-enough? guess x) (< (abs (- (square guess) x)) 0.001)) (define (improve guess x) (average guess (/ x guess))) (define (sqrt-iter guess x) (if (good-enough? guess x) guess (sqrt-iter (improve guess x) x))) (sqrt-iter 1.0 x))
そしてさらにsqrt内で変数xを自由変数として扱うと、そのスコープ内における各手続きに明示的に値を渡す必要がなくなる。
(define (sqrt x) (define (good-enough? guess) (< (abs (- (square guess) x)) 0.001)) (define (improve guess) (average guess (/ x guess))) (define (sqrt-iter guess) (if (good-enough? guess) guess (sqrt-iter (improve guess)))) (sqrt-iter 1.0))
xの値の探索は、その手続きが定義されている手続きの環境内で探索される。その範囲をレキシカルスコーピング(lexical scoping)という。(第三章で詳しく扱う)