SICPを読む(3)
飛ばしていた練習問題の消化
○ 問題 1.4
C++にずっぷりと使った身としては、かなり奇妙な感じに思える構文。
a + abs(b) を行うような関数だけれども、
というのが、なじめなくて一見した感じでは「む?」と考えてしまう。
とりあえずは、こんなサンプルを打って動作を確認
(define (a-plush-abs-b a b) ((if (> b 0) + -) a b)) (print (a-plush-abs-b 10 5)) (print (a-plush-abs-b 10 -5))
(結果)
15
15
振る舞いを考えてみると"(if (> b 0) + -)"の部分が、bが0より大きい場合には、+(プラス)を
返し、小さい場合には-(マイナス)を返す。
よって、bが0より大きい場合には"(+ a b)"となり、bが負の数の場合"(- a b)"となる。
よって、"a + abs(b)"として用いることができる。
○ 問題 1.5
まずはまとめをしてみる。
作用的順序による評価は、引数として渡すときに評価を行う方法で、正規順序の評価は、基本的演算子が
でてくるまでは式の置き換えを繰り返しす。
すなわち、
(define (sum a b) (+ a b))
という関数があったとして、
(sum (+ 10 20) (- 20 10)) ||M として評価した場合。 作用的順序による評価では、 >|| 1. (sum (+ 10 20) (- 20 10)) 2. (sum 30 10) 3. (+ 30 10) 4. 40
といった手順で評価され、正規順序による評価では
1. (sum (+ 10 20) (- 20 10)) 2. (+ (+ 10 20) (- 20 10)) 3. (+ 30 10) 4. 0
といった手順で評価される。
さて、問題の
(define (p) (p)) (define (test x y) (if (= x 0) 0 y)) (test 0 (p))
を考えてみる。
正規順序による評価では
1. (test 0 (p)) 2. (if (= x 0) 0 (p)) 3. 0
となる。
注目するべき点は、2.の"(= x 0)"から"(p)"を評価する必要が無いという点にある。
作用的順序では、
1. (test 0 (p)) 2. (test 0 (p)) 3. (test 0 (p)) ...
となり、"(define (p) (p))"の定義により、再起的に"(p)"が評価され続け、結果にたどり着くことが
できない。
ちなみに、同じプログラムをGaucheで実行してみると、当然応答しなかった