SICP第1章 手続きによる抽象の構築(1)

1.1 プログラムの要素

基本式
言語が関わる最も単純なものを表す
組合せ法
より単純なものから合成物を作る
抽象化法
合成物に名をつけ、単一のものとして扱う

1.1.1式

schemeでは前置記法を採用している。慣れるまでが大変かも?
(+ 137 349)
;;137 + 349

(+ 21 35 12 7) ;;21 + 35 + 12 + 7

(+ (* 3 5) (- 10 6)) ;;(3 * 5) + (10 - 6)

1.1.2 組合せの評価

defineをつかって値と名前の対応付け。いわゆる変数の宣言。

当たり前だけど、値と名前の対応付けを解釈系は記憶している。その記憶のことを(大域)環境という。大域があるなら局所もあるのかな。

1.1.3 組合せの評価

    組合せの評価
  1. 組合せの部分式を評価する
  2. 最左部分式の値である手続き(演算子)を、残りの部分式の値である引数(被演算子)に作用させる
すなわち評価の規則は、本質的に再帰的(recursive)である
一般的評価規則の例外を特殊形式(special forms)と言い、defineもそのうちの1つ。

1.1.4 合成手続き

合成手続きの作り方。例として二乗を返す合成手続きをサンプルにあげている。基本手続きが変数ならこっちは関数みたいなもの?
(define (square x) (* x x))

1.1.5 手続き作用の置き換えモデル

作用的順序と正規順序の違いについて。

作用的順序
引数を評価し、作用させる
正規的順序
完全に展開し、簡約する
通常lispは作用的順序の評価を行うらしい。正規順序は必要になるまで評価を行わないってことだと思うけど、遅延評価って意味なのかな。遅延評価を知らないから何とも言えないけど。

1.1.6 条件式と述語

特殊形式「cond」と「if」について。condの方は条件(述語)を複数指定できるけど、ifは1つのみ。他の言語でいうelseifがcondにはあるけど、(schemeの)ifにはelseしかない感じ。

論理演算も使えて、andやor、notがある。andとorは特殊形式で、notは通常の手続き。手続きっていう言葉の意味が自分の中でちょっと曖昧かもしれない。

問題1.1

手計算でやって、実際に動かして答え合わせをした。

問題1.2
(/ (+ 5 4) (- 2 (- 3 (+ 6 (/ 4 5)))))(* 3 (- 6 2) (- 2 7)))
;;-37150

問題1.3

(define (square x) (* x x))
(define (square_add x y) (+ (square x) (square y)))

(define (ex1_3 x y z) (if (< x y) (cond ((< x z) (square_add y z)) (else (square_add x y))) (cond ((< y z) (square_add x z)) (else (square_add x y))) ) )

結構時間かけちゃった。あらかじめsquareとsquare_addを定義してなるべく()を減らす作戦。書き終わった後に気づいたんだけど、最初の分岐はifなのにその次はcondなんだよね。両方ifでいいのにね。

問題1.4

問題の意味がうまく汲み取れないけど、多分「Schemeはこんなこともできるんだぜ!すげーだろ!」ってことを言ってるんだと思う。
((if (> b 0) + -) a b))
a = 3,b = -2
(- 3 -2) -> 5
a = 3, b = 2
(+ 3 2) -> 5
引数の値によって手続きも変えられるってことかな。

問題1.5

これも結構理解できるまで時間がかかった。

作用的順序の場合(test 0 (p))で先に(p)を評価する。けれど(p)の評価した時の結果が(p)だから無限ループになる。

(test 0 (p))
(p)を先に評価
(test 0 (p))
以降繰り返し…
正規順序の場合は、(p)を評価するのは後回しにするから無限ループにはならないで済む
(test 0 (p))
(if( (= 0 0)) 0 p))
(= 0 0)が#tだから0を返す