開発環境
- OS X Mavericks - Apple(OS)
- Emacs (CUI)、BBEdit - Bare Bones Software, Inc. (GUI) (Text Editor)
- Scheme (プログラミング言語)
- Gauche (処理系)
計算機プログラムの構造と解釈(Gerald Jay Sussman(原著)、Julie Sussman(原著)、Harold Abelson(原著)、和田 英一(翻訳)、ピアソンエデュケーション、原書: Structure and Interpretation of Computer Programs (MIT Electrical Engineering and Computer Science)(SICP))の1(手続きによる抽象の構築)、1.1(プログラミングの要素)、1.1.7(例: Newton法による平方根)、問題 1.6.を解いてみる。
その他参考書籍
- Instructor's Manual to Accompany Structure & Interpretation of Computer Programs
- プログラミングGauche (Kahuaプロジェクト (著), 川合 史朗 (監修), オライリージャパン)
問題 1.6.
Lispは作用的順序の評価を使っていることに注意する必要がある。
new-ifを使用した場合。
- (good-enough? guess x)を評価
- guessを評価
- (sqrt-iter (improve guess x) x)を評価
- (improve guess x)を評価(guess1とする)
- (sqrt-iter guess1 x)を評価
- (good-enough? guess1 x)を評価
- guess1を評価
- (sqrt-iter (improve guess1 x) x)を評価
- (improve guess1 x)を評価(guess2とする)
- (sqrt-iter guess2 x)を評価
- (good-enough? guess2 x)を評価
- 1-5を循環
特殊形式ifを使った場合はpredicateがtrueの場合、else-clauseが評価されないので循環することはない。このことが、ifは特殊形式であり、condを利用し、普通の手続きとして定義してはいけない理由。
確認。
コード(BBEdit, Emacs)
sample.scm
#!/usr/bin/env gosh
;; -*- coding: utf-8 -*-
(define (square x) (* x x))
(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)))
(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 (sqrt x)
(sqrt-iter 1.0 x))
入出力結果(Terminal, REPL(Read, Eval, Print, Loop))
$ gosh
gosh> (load "./sample.scm")
#t
gosh> (sqrt 4)
^C*** UNHANDLED-SIGNAL-ERROR: unhandled signal 2 (SIGINT)
Stack Trace:
_______________________________________
0 x
1 (abs (- (square guess) x))
At line 23 of "./sample.scm"
2 (good-enough? guess x)
At line 11 of "./sample.scm"
3 (sqrt-iter (improve guess x) x)
At line 13 of "./sample.scm"
4 (sqrt-iter (improve guess x) x)
At line 13 of "./sample.scm"
5 (sqrt-iter (improve guess x) x)
At line 13 of "./sample.scm"
6 (sqrt-iter (improve guess x) x)
At line 13 of "./sample.scm"
7 (sqrt-iter (improve guess x) x)
At line 13 of "./sample.scm"
8 (sqrt-iter (improve guess x) x)
At line 13 of "./sample.scm"
9 (sqrt-iter (improve guess x) x)
At line 13 of "./sample.scm"
10 (sqrt-iter (improve guess x) x)
At line 13 of "./sample.scm"
11 (sqrt-iter (improve guess x) x)
At line 13 of "./sample.scm"
12 (sqrt-iter (improve guess x) x)
At line 13 of "./sample.scm"
13 (sqrt-iter (improve guess x) x)
At line 13 of "./sample.scm"
14 (sqrt-iter (improve guess x) x)
At line 13 of "./sample.scm"
15 (sqrt-iter (improve guess x) x)
At line 13 of "./sample.scm"
16 (sqrt-iter (improve guess x) x)
At line 13 of "./sample.scm"
17 (sqrt-iter (improve guess x) x)
At line 13 of "./sample.scm"
18 (sqrt-iter (improve guess x) x)
At line 13 of "./sample.scm"
19 (sqrt-iter (improve guess x) x)
At line 13 of "./sample.scm"
20 (sqrt-iter (improve guess x) x)
At line 13 of "./sample.scm"
21 (sqrt-iter (improve guess x) x)
At line 13 of "./sample.scm"
22 (sqrt-iter (improve guess x) x)
At line 13 of "./sample.scm"
23 (sqrt-iter (improve guess x) x)
At line 13 of "./sample.scm"
24 (sqrt-iter (improve guess x) x)
At line 13 of "./sample.scm"
25 (sqrt-iter (improve guess x) x)
At line 13 of "./sample.scm"
26 (sqrt-iter (improve guess x) x)
At line 13 of "./sample.scm"
27 (sqrt-iter (improve guess x) x)
At line 13 of "./sample.scm"
28 (sqrt-iter (improve guess x) x)
At line 13 of "./sample.scm"
29 (sqrt-iter (improve guess x) x)
At line 13 of "./sample.scm"
... (more stack dump truncated)
gosh> (exit)
$
おまけ。
正規順序の評価を使っているHaskellの場合はifは特殊形式ではなく普通の手続きとして定義出来る。
コード(BBEdit, Emacs)
sample.hs
{-# OPTIONS -Wall -Werror *-}
module Main where
main :: IO ()
main = print $ mySqrt 4
square :: Double -> Double
square x = x * x
newIf :: Bool -> a -> a -> a
newIf predicate x y | predicate = x
| otherwise = y
sqrtIter :: Double -> Double -> Double
sqrtIter guess x = newIf (goodEnough guess x) guess
(sqrtIter (improve guess x) x)
improve :: Double -> Double -> Double
improve guess x = average guess (x / guess)
average :: Double -> Double -> Double
average x y = (x + y) / 2
goodEnough :: Double -> Double -> Bool
goodEnough guess x = (abs $ (square guess) - x) ≪ 0.001
mySqrt :: Double -> Double
mySqrt = sqrtIter 1.0
入出力結果(Terminal, runghc)
$ runghc Sample.hs 2.0000000929222947 $
0 コメント:
コメントを投稿