一人読書会 「計算機プログラムの構造と解釈」 (10)
1.1.8 ブラックボックス抽象としての手続き
新しい言語を覚えようとすると、まず変数の宣言の仕方や、制御構文を覚えるが、1つなにか知っていればそれらを覚えるくらいは何のことはない。
しかし、パラダイムが異なるとこれは大変。多分プログラム言語で習得が難解とされていることがらは、パラダイムの相違に起因しているのではないかと、この章を読んで思った。
例えば、C言語のポインターなんて、高級言語であるC言語に、アセンブラのパラダイムが持ち込まれているのが難解といわれる原因だろうし、構造化言語に浸かっていればオブジェクト指向はちんぷんかんぷんだろう。ただし、逆からみれば、あまりにも自明過ぎて、何が難解か分からないだろう。
なぜ、そんなことを思ったかというと、ちょっと前に、クロージャー関数がはやった(?)が、当初何のことやら分からなかった。また、レキシカル変数とか言う用語の意味もよく分からなかった。そこそこプログラムを書いていたにもかかわらず。
それらの概念が、自分が主にやってきた言語には無かったから、理解するのに手間取ったが、この章で述べられている用語をきちんと理解していれば、そのどちらも悩むことなく理解できただろうなぁと。
自分の興味の変遷は Java → JavaScript → Python → Scheme な感じだが、今思うと何というか自然に思える。
手続き抽象(procedural abstraction)
分割統治法を用いるとき、部分の手続きがどう結果を計算するのかには関心を持たない。Wikipediaでは、「アルゴリズムは自由に選択できる」とされている。それは「手続き」ではなく、「手続き抽象(procedural abstraction)」である。
局所名
手続きの仮パラメータは、どんな名前でもかまわない。手続き本体に対して局所的で無ければならない。
束縛変数(bound variable)
手続き定義のなかで、仮パラメータはどんな名前でもかまわないし、名前をすべて変更しても手続きの意味は変わらないという意味で、手続き定義は、仮パラメータを束縛している(bind)。そういう名前を束縛変数(bound variable)という。変数が束縛されていなければ、自由である(free)。
有効範囲(Scope)
名前が束縛されている式の範囲
ブロック構造(block structure)
定義の入れ子。単純な名前保護の機構。ここで作成した、sqrt2 関数から呼び出される関数、average、square、good-enough? ・・・ を sqrt2 関数のブロックの中に定義できる。sqrt2 ブロックの外で、同名の手続きを定義しても、それぞれには影響を与えない。
(define (sqrt2 x) (define (average x y) (/ (+ x y) 2)) (define (square x) (* x x)) (define (good-enough? guess x) (< (abs (- (square guess) x)) 0.001)) (define (improve guess x) (average guess (/ x guess))) (define (sqrt-itr guess x) (if (good-enough? guess x) guess (sqrt-itr (improve guess x) x))) (sqrt-itr 1.0 x))
静的有効範囲(lexicacl scoping)
上記例で、x は、sqrt2 の定義に束縛されている。なので、その内側の関数は、x の有効範囲内にあるため明示的に渡さなくてもよいので、自由変数にできる。こうしたやり方を静的有効範囲(lexical scoping) という。
(define (sqrt2 x) (define (average a b) (/ (+ a b) 2)) (define (good-enough? guess) (< (abs (- (* guess guess) x)) 0.001)) (define (improve guess) (average guess (/ x guess))) (define (sqrt-itr guess) (if (good-enough? guess) guess (sqrt-itr (improve guess)))) (sqrt-itr 1.0))
今日はここまで。