2008/12/31

【scheme】ブロック内スコープ@SICP

平方根を求めるsqrt関数 先日のもの(【scheme】1.1.7 例:Newton法による平方根@SICP

(define avarage
  (lambda (x y)
    (/ (+ x y) 2)))
(avarage 10 20);;=> 15
(avarage 5.0 8.0);;=> 6.5

(define square
  (lambda (x)
    (* x x)))
(square 5);;=> 25
(square 12);;=> 144

(define improve
  (lambda (guess x)
    (avarage guess (/ x guess))))
(improve 10.0 5.0);;=> 5.25
(improve 1.5 2.5);;=> 1.5833333333333335

(define good-enough?
  (lambda (guess x)
    (< (abs (- (square guess) x)) 0.001)))

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

(define sqrt
  (lambda (x)
    (sqrt-iter 1.0 x)))

(sqrt 9);;=> 3.00009155413138
(sqrt (+ 100 37));;=> 11.704699917758145
(sqrt (+ (sqrt 2)(sqrt 3)));;=> 1.7739279023207892
(square (sqrt 1000));;=> 1000.000369924366

各関数をsqrt定義内に納めたもの。

;; local scope difinition
(define sqrt
  (lambda (x)
    (define square
      (lambda (x)
        (* x x)))
    (define avarage
      (lambda (x y)
        (/ (+ x y) 2)))
    (define improve
      (lambda (guess x)
        (avarage guess (/ x guess))))
    (define good-enough?
      (lambda (guess x)
        (< (abs (- (square guess) x)) 0.001)))
    (define sqrt-iter
      (lambda (guess x)
        (if (good-enough? guess x)
            guess
            (sqrt-iter (improve guess x) x))))
    (sqrt-iter 1.0 x)))
(sqrt 9);;=> 3.00009155413138

sqrtのパラメータxのブロック内スコープ(レキシカルスコープ)を利用したもの。 xを利用した関数を返すようにすればクロージャできそうでつね。

(define square
  (lambda (x)
    (* x x)))
(define avarage
  (lambda (x y)
    (/ (+ x y) 2)))

(define sqrt
  (lambda (x)
    (define improve
      (lambda (guess)
        (avarage guess (/ x guess))))
    (define good-enough?
      (lambda (guess)
        (< (abs (- (square guess) x)) 0.001)))
    (define sqrt-iter
      (lambda (guess)
        (if (good-enough? guess)
            guess
            (sqrt-iter (improve guess)))))
    (sqrt-iter 1.0)))
(sqrt 9);;=> 3.00009155413138

0 件のコメント:

コメントを投稿