ブログトップ 記事一覧 ログイン 無料ブログ開設

乱筆乱文お許し下さいorz このページをアンテナに追加 RSSフィード

2011-06-04

計算機プログラムの構造と解釈(SICP) 勉強メモ5

2週間ほど急がしくて勉強が出来なかった。

今日から再開。

とりあえず、前回勉強した分をUPしてなかったのでUP.

問題1.6だけ。

問題1.7で悩んでる。




;問題1.6
(define (new-if predicate then-clause else-clause)
  (cond (predicate then-clause)
        (else else-clause)))

;(define (sqrt-iter guess x)
;  (new-if (good-enough? guess x)
;          guess
;          (sqrt-iter (improve guess x)
;                     x)))

;上のsqrt-iterを実行したら、無限ループに陥った。
;ifとは
; (if <predicate> <consequent> <alternative>)
;である。
;if式の評価はまず式の述語<predicate>部分を評価する。
;<predicate>の評価の結果が真なら、解釈系は帰結部<consequent>を"評価しその値を返す"。
;
;一方、condは
; (cond (<p1> <e1>)
;       (<p2> <e2>)
;       (<pn> <en>))
;である。
;condはまず<p1>を評価し、その値が偽なら<p2>を評価する。
;その手順が真である述語が見つかったら、解釈駅はその節の対応する<e>の値をこの条件式の値として返す。
;
;つまり、new-ifではelse-clauseの値が評価されず、else-clauseがそのまま返り値として返ってきている。
;よって無限ループとなる。
;
;ifを使ったsqrt-iter
;gosh> (trace sqrt-iter)
;#<closure #f>
;gosh> (sqrt 9)
;0:(sqrt-iter 1.0 9)
;1:  (sqrt-iter 5.0 9)
;2:    (sqrt-iter 3.4 9)
;3:      (sqrt-iter 3.023529411764706 9)
;4:        (sqrt-iter 3.00009155413138 9)
;          ->3.00009155413138
;        ->3.00009155413138
;      ->3.00009155413138
;    ->3.00009155413138
;  ->3.00009155413138
;trace: sqrt-iter has been called 5 times.
;3.00009155413138
;
;new-ifを使ったsqrt-iter
;(sqrt-iter (improve guess x) x)
;  At line 448 of "/users/nishizawaiori/Study/book/lisp/sicp/sicp.scm
;この無限ループ
;
;これにより、(improve guess x)が評価されず、平均値が変わらずずっとgood-enough?で#fが返り、無限ループに陥ることが解る。
;

valvallowvalvallow 2011/06/05 12:28 このnew-ifが無限ループになるのは、new-ifが「手続き」だからではないでしょうか。
特殊形式であるifは、まずpredicateだけ評価し、その結果によってthen-clauseを評価するかelse-clauseを評価するかを決定します。
ですが、このnew-ifは「手続き」なので、predicateが評価されるのと同じタイミング(語弊があるかも)でthen-clauseもelse-clauseも評価しています。

手続きの呼び出しは、呼び出し前に全ての引数が評価されます。
特殊形式は呼び出し時に引数の評価を行ないません。

sqrt-iterでは(good-enough? guess x)が再帰の停止条件なので、(good-enough? guess x)が#fになった場合はthen-clauseであるguessのみが評価されて欲しいはずですが、new-ifは(good-enough? guess x)が評価されるタイミングで(sqrt-iter (improve guess x) x)の方も評価されているので無限に再帰しています。

valvallowvalvallow 2011/06/05 12:51 結局何が言いたいかというと、こういうことです。

(new-if #f (print "hoge")(print "fuga"))
;; hoge
;; fuga
;; #<undef>

Iori_NishizawaIori_Nishizawa 2011/06/05 14:23 あ、なるほど。
「ifが特殊形式だから」っていう理解をしていたんですが、確かに正確には「new-ifが手続きだから」ですね。

(new-if #f (print "hoge")(print "fuga"))
;; hoge
;; fuga
;; #<undef>

これが特に解りやすかったです。

ありがとうございました!!

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/Iori_Nishizawa/20110604/1307173305