Lisp Yu Yan Scheme Bi Ji Yi

复合过程

#lang racket

; run it with "racket xxx.scm"
; the outputs are:
; 49
; 25
; #f

(define (square x)
    (* x x))

(define (sum-of-squares x y)
    (+ (square x) (square y)))

(square 7)
(sum-of-squares 3 4)

(define x 100)
(< x 99)

条件表达式

(define (abs1 x)
  (cond ((> x 0) x)
        ((= x 0) 0)
        ((< x 0) (- x))))

(define (abs2 x)
  (cond ((< x 0) (- x))
        (else x)))

(define (abs3 x)
  (if (< x 0)
      (- x)
      x))

运算符为复合表达式

(define (a-plus-abs-b a b)
    ((if (< b 0) - +) a b)

(a-plus-abs-b 4 3) ; => 7
(a-plus-abs-b 4 -3) ; => 7

谓词

; the outputs are:
; #t
; #f
; #t
; #t

(define (between n x y)
    (and (> n x) (< x y)))

(define (=> x y)
    (or (> x y) (= x y)))

(define (=< x y)
    (not (> x y)))

(between 7 5 10)
(=> 7 8)
(=< 7 8)
(and (> 1 0) (> 2 0) (> 3 0))

牛顿法:

; 牛顿法求平方根
; 如果对x的平方根的值有了一个猜测y,
; 那么通过一个简单操作可以得到一个更好的猜测:
; 只需要求出 y 和 x/y 的平均值

(define (diff y x)
    (abs (- (* y y) x)))

(define (improve y x)
    (/ (+ y (/ x y)) 2))

(define (good-enough? y x)
    (< (diff y x) 0.00001))

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

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

(sqrt2 2)

当开方数值非常小或非常大时,如 0.123e-72e30,上面检测good-enough时就不好使了,更好的办法是检测猜测数值变化的比率。

; 牛顿法求平方根 (改进版)
; 如果对x的平方根的值有了一个猜测y,
; 那么通过一个简单操作可以得到一个更好的猜测:
; 只需要求出 y 和 x/y 的平均值
; sqrt() is a BIF (Built-in Function)

(define (grow-rate y x)
    (abs (/ (- (* y y) x) x)))

(define (improve y x)
    (/ (+ y (/ x y)) 2))

(define (good-enough? y x)
    (< (grow-rate y x) 0.00001))

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

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


(sqrt2 2e30)
(sqrt 2e30)
(sqrt2 1.23e-7)
(sqrt 1.23e-7)

为了解决潜在的命令空间污染问题,可以用块结构将函数重写

(define (sqrt2 x)
    (define (sqrt-iter guess)
        (if (good-enough? guess)
            guess
            (sqrt-iter (improve guess))))
    (define (good-enough? guess)
        (< (abs (- (/ (* guess guess) x) 1)) 0.00001))
    (define (improve y)
        (/ (+ (/ x y) y) 2))
    (sqrt-iter 1.0))

注意,在这个函数里我们省略了 sqrt-iter, good-enough?, 和 improve的形参中的x,因为在这些过程中可以直接用由sqrt2传入的自由变量x