一人読書会 「計算機プログラムの構造と解釈」 (1)
「計算機プログラムの構造と解釈」 を購入。しっかりと読み込みたいので、1年くらいかけて一人読書会としゃれ込もうと思う。
・・・電車で読むだけではもったいない。
1.手続きによる抽象の構築
まず、全編を通して、プログラムの説明には、C や Java や Python ではなく、Lisp の方言である、Scheme (スキーム) を使用する。
そもそも、Scheme の設計者である、ジェラルド・ジェイ・サスマン が、本書の著者。
amazon のレビューをみると、訳に対する苦情が多いようだが、自分も最初のページで違和感を感じた。デバッグのことを「虫とり」とか。
ただ、訳者が、1931年生まれの先生ということを知ると、訳の雰囲気の違和感も哲学書のような雰囲気を醸し出してきた。自分はこういう訳も嫌いではない。
で、本書では、 cheme がわからないと話にならないので、最初の章は、文法および考え方の説明に費やされている。
こちらに簡単にまとめた。さらにまとめると、
確認用の処理系には、DrScheme を使用することとする。
式
手続きの作用を表現。括弧で囲んで、組合せと呼ぶ。
> (+ 1 2) 3
この例だと、加算(+) が、手続きを表す演算子(オペレーター)、1、2 が作用される被演算子(オペランド)
演算子を左端に書く記法を、前置記法という。利点として、任意個数の引数をとることができる、組合せを入れ子にできる。
特殊形式(special forms)
引数に作用しない場合、組合せとは呼ばず、特殊形式という。たとえば、define
> (define x 2)
これで、変数 x に 2 をセットする。
合成手続き
define をつかって、演算に名前をつけることができる。自乗を行う演算に名前をつけてみる。
> (define (square x) (* x x)) > (square 2) 4
条件式と述語
cond ・・・ 場合分け
if ・・・ 場合が2つの場合
論理演算子
and、or、not
用例は、こちら を参照。
問題
問題1.1
入力して確認。
問題1.2
これでよいと思うけど・・・
> (/ (+ 5 4 (- 2 (- 3 (+ 6 (/ 4 5))))) (* 3 (- 6 2) (- 2 7))) -37/150
問題1.3
いままで経験した言語との考え方の違いを思い知る。
今の知識、思考方法では、こんな感じにしかかけない・・・
変数や配列を使わずに、2番目に大きい値を取得するって困難。
> (define (smaller x y) (if (< x y) x y)) > (define (last x y z) (smaller x (smaller y z))) > (define (square x) (* x x)) > (define (q1_3 x y z) (+ (square (if (> x (last x y z)) x (last x y z))) (square (if (> y (last x y z)) y (last x y z))))) > (q1_3 4 3 2) 25
問題1.4
引数 b が 負の値の場合、符号を反転し絶対値を取得し、a と加算する
おーなんと、被演算子に演算子を置くと、その演算子が作用するのか!
> (define (a-plus-abs-b a b) ((if (> b 0) + -) a b)) > (a-plus-abs-b 2 -3) 5
おー結構しんどいなー。今日はここまで。
ゆっくりでもいいから何とか続けていきたい。。。