手続きによる抽象の構築(9)

また仕事が忙しくなってきそうな雰囲気!

問題 1.8

立方根をNewton法で求める関数cube-rootを作成。

(define (cube-root-iter guess variation x)
(if (good-enough? guess variation)
guess
(cube-root-iter (improve guess x)
(- guess (improve guess x))
x)))
(define (improve guess x)
(/
(+
(/ x (* guess guess))
(* 2 guess))
3))
(define (average x y)
(/ (+ x y) 2))
(define (good-enough? guess variation)
(< (abs (* variation 1000)) guess))
(define (cube-root x)
(cube-root-iter 1.0 1.0 x))


gosh> (cube-root 1)
1.0
gosh> (cube-root 2)
1.2599210500177698
gosh> (define ans (cube-root 3))
ans
gosh> (* ans ans ans)
3.0000013684348827
gosh> (cube-root 8)
2.000000000012062
gosh> (cube-root 27)
3.0000005410641766

1.1.8 ブラックボックス抽出としての手続き

手続きのブラックボックス化のお話・・・ってタイトル通りか。手続きを利用する側からは実装方法はブラックボックスとして作っても問題なく、またそうあるべきだよね、というお話。これはLispに限った話ではないので、既に知っている。

続いて、仮パラメタ名は局所的であるという話。重要そうな文章が出てきたので写経。

手続きの仮パラメタには、手続き定義の中で、仮パラメタがどんな名前を持っていても構わないという、特別な役目がある。そういう名前を束縛変数(bound variable)といい、手続き定義は仮パラメタを束縛する(bind)という。定義の中で束縛変数名を統一的に付け替えても、手続き定義の意味は変わらない。変数が束縛されていなければ、自由である(free)という。名前が束縛されている式の範囲を有効範囲(scope)という。手続き定義の中では、その手続きの仮パラメタとして宣言された束縛変数の有効範囲は、その手続きの本体である。

原書に戻ろう。

A formal parameter of procedure has a very special role in the procedure definition, in that it doesn't matter what name the formal parameter has. Such a name is called a bound variable, and we say that the procedure definition binds its formal parameters. The meaning of procedure definition is unchanged if a bound variable is consistently renamed throughout the definition. If a variable is not bound, we say that it is free. The set of expressions for which a binding defines a name is called the scope of that name. In a procedure definition, the bound variables declared as the formal parameters of the procedure have the body of the procedure as their scope.

freeの概念がよくわからない。何に対してfreeなのか?いろいろ考えた結果、この手続きに対して、なのではないかという結論に至った。手続きが蜘蛛みたいなもんで、その中で変数名として使われたものは捕捉(capture)されてしまうイメージ。仮パラメタ名であるxやguessは手続きに捕捉されているが、absや+などは捕縛されていないので、freeである。変数名になり得るありとあらゆる名前がfreeな空間があって、各手続きは、必要なものを捕縛するイメージ。うーん、いまいちな比喩だ。

続いて、内部定義とブロック構造のお話。関数内関数の定義方法が載っていた。C言語的思考からするとビックリだけど、C++まで行ってネームスペースやクラスのプライベート関数を理解しているので、問題なく理解できた。その際に、先ほど上で出した答えと関係する文章が出てきたので、転記。

補助手続きの定義の内部化する他、それらを単純化出来る。xはsqrtの定義に束縛されているから、sqrtの内部で定義するgood-enough?、improveおよびsqrt-iterの手続きはxの有効範囲内である。

xはsqrtの定義に束縛されているから
xはsqrtの定義に束縛されているから
xはsqrtの定義に束縛されているから
どうやら、さっきの考えで合っていたようだ、とてもうれしい。

ここでようやく「1.1 プログラムの要素」が終了。自分としては、悪くないペースで進んでいます。遅すぎないのはもちろん、早すぎないのも重要かな、と思います。早すぎるのは無理をしていますから、半年はかかるであろうこの本の攻略には無理はよくないです。気長にじっくり行きます。

シェアする

  • このエントリーをはてなブックマークに追加

フォローする