SICPを読む。
学生のうちに読んでおけーという電波を受信したので噂に名高い、SICPことamazon:計算機プログラムの構造と解釈を読んでみる。英語版はハードカバーで固かったですが、日本語版はやわらかいですね。あと日本語なので読みやすいですね。
日本語訳がどうこうって噂はすこし聞いたことがありましたが、別に普通かな。確かに「ああこれ翻訳文なんだろうな」とわかる文章も多いかも。「翻訳し過ぎ」の感があるってことか。
コンピュータに関わってる人達の多くは日本語日本語した文章は好きじゃありません。「Schemeではフィールドのスコープはオブジェクト内にローカライズされ、それらにアクセスするためにはメソッドを用いる」みたいな、門外漢からすれば「何語?」って聞かれるような文章が好きなのです。
でも俺はほぼ門外漢なのでたいしてSICPの文章に違和感を感じなかった。
プログラムのことを「符」とか書いてるような、前世紀の書物は流石に勘弁してほしいけど。あとプログラムが全部大文字だったりとか。なんで昔の人は小文字の方が読みやすいって気付かなかったんだろう……
問題1.2から1.6までやった。
問題1.2
(/ (+ 5 4 ( - 2 (- 3 (+ 6 (/ 4 5))))) (* 3 (- 6 2) (- 2 7))) -0.24666666666666667
問題1.3
(define (p a b c) (define (f x y) (+ (expt x 2) (expt y 2))) (if (> a b) (if (> b c) (f a b) (f a c)) (if (> a c) (f a b) (f c b)))) p (p 1 2 3) 13 ; 2^2 + 3^2 (p 10 100 1000) 1010000 ; 1000^2 + 100^2 ですね。
if文が超気持ち悪い。
なんか別解
(define (q a b c)
(define (q1 x y) (+ (expt x 2) (expt y 2)))
(cond
((and (<= a b) (<= a c)) (q1 b c))
((and (<= b a) (<= b c)) (q1 a c))
((and (<= c a) (<= c b)) (q1 a b))))
q
(q 1 2 3)
13
(q 10 100 1000)
1010000さっきよりまし、かなあ。どうだろう。=取れる所あるけど、取らなくても同じだよなあ。
問題1.4
(define (a-plus-abs-b a b) ((if (> b 0) + -) a b))
(a-plus-abs-b 30 -6)で36とかでしょう。で、そうでした。演算子そのものが、当然のように被演算子になるのが気持ち良いですね。
問題1.5
(define (p) (p)) (define (test x y) (if (= x 0) 0 y)) (test 0 (p))
動かすまでわからんかった。pは無限再帰です。
正規順序で評価してる場合は、(test 0 (p))は、if文に展開されるので、pを評価する必要無しに0となる。でも実際の処理系では引数が展開されて渡されるから、pが評価されてしまう。なので(test 0 (p))も無限再帰に。
問題1.6
(define (sqrt x)
(define (sqrt-iter guess x)
(define (improve guess x)
(average guess (/ x guess)))
(define (average x y) (/ (+ x y) 2))
(define (good-enough? guess x)
(< (abs (- (square guess) x)) 0.001))
(define (square x) (* x x))
(define (new-if predicate then-clause else-clause)
(cond (predicate then-clause)
(else else-clause)))
(new-if (good-enough? guess x)
guess
(sqrt-iter (improve guess x) x)))
(sqrt-iter 1.0 x))
sqrt
(sqrt 2.0)えーとこれも帰ってこないですね。もしや1.5と同じこと?
(define (p) (p)) (if (= 0 0) 0 (p)) (define (new-if predicate then-clause else-clause) (cond (predicate then-clause) (else else-clause))) (new-if (= 0 0) 0 (p))
うん、帰ってこないですよね。(new-if (= 0 0) 0 (p))は、引数の評価を先にやってから、その値をnew-ifに渡します。でその後cond節に展開する。なのでpを展開し続けてしまいます。
問題1.6も同様に、sqrt-iterを再帰的に展開し続けてくるので帰ってきません。ということでifはthen節とelse節、条件に合った方だけ評価するようですね。
テスト。
(if (= 1 0) (p) 0) 0
おーけー。
眠い。