一些程序

Programs must be written for people to read, and only incidentally for machines to execute.

(按值调用的)Y组合子

(define Y
  (lambda (h)
    ((lambda (f) (f f))
     (lambda (g)
       (h (lambda (x) ((g g) x)))))))

Fibonacci数列

(define (fib n)
  (if (< n 2)
      n
      (+ (fib (- n 1))
         (fib (- n 2)))))
(define (fib n)
  (let iter ((a 0) (b 1) (c 0))
    (if (= c n)
        a
        (iter b (+ a b) (+ c 1)))))

阶乘

(define (fact n)
  (if (= n 0)
      1
      (* n (fact (- n 1)))))

Knuth箭头记号

(define ((up n) a b)
  (cond ((zero? n) (* a b))
        ((zero? b) 1)
        (else
         ((up (sub1 n)) a ((up n) a (sub1 b))))))

葛立恒数

(define ((repeated n) f)
  (if (zero? n)
      identity
      (compose f ((repeated (sub1 n)) f))))
(define (f n) ((up n) 3 3))
(define f64 ((repeated 64) f))
(define G (f64 4))

Knuth洗牌算法

(define (shuffle! v)
  (define l (vector-length v))
  (let iter ((i l))
    (unless (< i 2)
      (vector-swap! v (random i) (- i 1))
      (iter (- i 1)))))

排列数和组合数

(define (P n k)
  (let iter ((n n) (k k) (r 1))
    (if (= k 0)
        r
        (iter (- n 1) (- k 1) (* n r)))))
(define (C n k)
  (let ((k (min k (- n k))))
    (/ (P n k) (fact k))))

计算置换符号

(define (sign-of-permutation permutation)
  (define p (vector-copy permutation))
  (define l (vector-length p))
  (define q (make-vector l))
  (let iter ((i 0))
    (unless (= i l)
      (define x (vector-ref p i))
      (vector-set! q x i)
      (iter (+ i 1))))
  (let iter ((i 0) (s 1))
    (if (= i l)
        s
        (let ((x (vector-ref p i)))
          (if (= i x)
              (iter (+ i 1) s)
              (let ((j (vector-ref q i)))
                (vector-swap! p i j)
                (vector-swap! q x i)
                (iter (+ i 1) (- s))))))))

笛卡尔积

(define (product . lst*)
  (if (null? lst*)
      '(())
      (append-map
       (lambda (d)
         (map (lambda (a) (cons a d))
              (car lst*)))
       (apply product (cdr lst*)))))

Euclid算法

(define (gcd a b)
  (if (= b 0)
      a
      (gcd b (remainder a b))))

扩展Euclid算法

(define (ext-gcd a b)
  (if (= b 0)
      (values a 1 0)
      (let*-values
          (((q r) (quotient/remainder a b))
           ((d m n) (ext-gcd b r)))
        (values d n (- m (* q n))))))

Eratosthenes筛法 (Turner筛法)

(define (divides? a b)
  (= (remainder b a) 0))
(define (make-ints n)
  ($cons n (make-ints (+ n 1))))
(define (sieve $)
  ($cons ($car $)
         (sieve
          ($filter (lambda (x)
                     (not (divides? ($car $) x)))
                   ($cdr $)))))
(define primes
  (sieve (make-ints 2)))

进制转换

(define (base-convert n b)
  (let iter ((n n) (r '()))
    (if (= n 0)
        r
        (iter (quotient n b)
              (cons (remainder n b) r)))))

计数器

(define (make-counter)
  (let ((x -1))
    (lambda ()
      (set! x (+ x 1))
      x)))

de Casteljau算法

(define (make-pt x y) (vector 'pt x y))
(define (pt-x pt) (vector-ref pt 1))
(define (pt-y pt) (vector-ref pt 2))
(define (make-vec x y) (vector 'vec x y))
(define (vec-x vec) (vector-ref vec 1))
(define (vec-y vec) (vector-ref vec 2))
;pt- : pt * pt -> vec
(define (pt- p1 p2)
  (make-vec
   (- (pt-x p1) (pt-x p2))
   (- (pt-y p1) (pt-y p2))))
;pt+ : pt * vec -> pt
(define (pt+ p v)
  (make-pt
   (+ (pt-x p) (vec-x v))
   (+ (pt-y p) (vec-y v))))
;vec* : real * vec -> vec
(define (vec* k v)
  (make-vec
   (* k (vec-x v))
   (* k (vec-y v))))
;lerp : real -> pt * pt -> pt
(define ((lerp t) p1 p2)
  (pt+ p1 (vec* t (pt- p2 p1))))
;deCasteljau : pt* -> real -> pt
(define ((deCasteljau p*) t)
  (let iter ((p* p*))
    (if (null? (cdr p*))
        (car p*)
        (iter (map (lerp t)
                   (drop-right p* 1)
                   (cdr p*))))))

列表上的插入排序

(define (isort l)
  (if (null? l)
      '()
      (insert (car l) (isort (cdr l)))))
(define (insert x l)
  (cond ((null? l) (list x))
        ((<= x (car l)) (cons x l))
        (else
         (cons (car l)
               (insert x (cdr l))))))

列表上的快速排序

(define (qsort l)
  (if (or (null? l) (null? (cdr l)))
      l
      (let-values (((left middle right) (partition l)))
        (append (qsort left) middle (qsort right)))))
(define (partition l)
  (define pivot (car l))
  (let iter ((left '()) (middle '()) (right '()) (rest l))
    (cond ((null? rest) (values left middle right))
          ((< (car rest) pivot)
           (iter (cons (car rest) left) middle right (cdr rest)))
          ((= (car rest) pivot)
           (iter left (cons pivot middle) right (cdr rest)))
          (else
           (iter left middle (cons (car rest) right) (cdr rest))))))

一个模式匹配宏

(define-syntax match
  (syntax-rules (guard)
    ((_ v) (error 'match "~s" v))
    ((_ v (pat (guard g ...) e ...) cs ...)
     (let ((fk (lambda () (match v cs ...))))
       (ppat v pat (if (and g ...) (let () e ...) (fk)) (fk))))
    ((_ v (pat e ...) cs ...)
     (let ((fk (lambda () (match v cs ...))))
       (ppat v pat (let () e ...) (fk))))))
(define-syntax ppat
  (syntax-rules (unquote)
    ((_ v () kt kf) (if (null? v) kt kf))
    ((_ v (unquote var) kt kf) (let ((var v)) kt))
    ((_ v (x . y) kt kf)
     (if (pair? v)
         (let ((vx (car v)) (vy (cdr v)))
           (ppat vx x (ppat vy y kt kf) kf))
         kf))
    ((_ v lit kt kf) (if (eqv? v (quote lit)) kt kf))))

Church编码

(define zero
  (lambda (f)
    (lambda (x)
      x)))
(define one
  (lambda (f)
    (lambda (x)
      (f x))))
(define true
  (lambda (x)
    (lambda (y)
      x)))
(define false
  (lambda (x)
    (lambda (y)
      y)))
(define cons
  (lambda (x)
    (lambda (y)
      (lambda (m)
        ((m x) y)))))
(define car
  (lambda (p)
    (p true)))
(define cdr
  (lambda (p)
    (p false)))
(define succ
  (lambda (n)
    (lambda (f)
      (lambda (x)
        (f ((n f) x))))))
(define pred
  (lambda (n)
    (car
     ((n (lambda (p)
           ((cons (cdr p)) (succ (cdr p)))))
      ((cons zero) zero)))))

tagless-final

(define (varZ env) (car env))
(define ((varS vp) env)
  (vp (cdr env)))
(define ((lam e) env)
  (lambda (x)
    (e (cons x env))))
(define ((app e1 e2) env)
  ((e1 env) (e2 env)))

简单可扩展的模式匹配器

(define (empty-dict) '())
(define (ext-dict key val dict)
  (cons (list key val) dict))
(define (lookup key dict)
  (assq key dict))
(define (bd-val bd) (cadr bd))
;<var> ::= (? <symbol>)
;<seg-var> ::= (?? <symbol>)
(define (var-id v) (cadr v))
;<const> ::= <number>
;         |  <boolean>
;         |  <symbol>
(define (const? x)
  (or (number? x)
      (boolean? x)
      (symbol? x)))
(define (Const c)
  (lambda (x* dict succ fail)
    (cond ((null? x*) (fail))
          ((eqv? (car x*) c)
           (succ (cdr x*) dict fail))
          (else (fail)))))
(define (Var id)
  (lambda (x* dict succ fail)
    (if (null? x*)
        (fail)
        (let ((bd (lookup id dict)))
          (if bd
              (let ((val (bd-val bd)))
                (if (equal? val (car x*))
                    (succ (cdr x*) dict fail)
                    (fail)))
              (succ (cdr x*)
                    (ext-dict id (car x*) dict)
                    fail))))))
(define (Seq2 m1 m2)
  (lambda (x* dict succ fail)
    (m1 x* dict
        (lambda (x* dict fail)
          (m2 x* dict succ fail))
        fail)))
(define (Succ)
  (lambda (x* dict succ fail)
    (succ x* dict fail)))
(define (Fail)
  (lambda (x* dict succ fail)
    (fail)))
(define (Seq . m*)
  (if (null? m*)
      (Succ)
      (let iter ((m (car m*))
                 (m* (cdr m*)))
        (if (null? m*)
            m
            (iter (Seq2 m (car m*))
                  (cdr m*))))))
(define (List . m*)
  (let ((m (apply Seq m*)))
    (lambda (x* dict succ fail)
      (if (null? x*)
          (fail)
          (let ((x (car x*))
                (x* (cdr x*)))
            (if (or (null? x) (pair? x))
                (m x dict
                   (lambda (rest dict fail)
                     (if (null? rest)
                         (succ x* dict fail)
                         (fail)))
                   fail)
                (fail)))))))
(define (Seg-var id)
  (lambda (x* dict succ fail)
    (let ((bd (lookup id dict)))
      (if bd
          (let ((y* (bd-val bd)))
            (let iter ((y* y*) (x* x*))
              (cond ((null? y*) (succ x* dict fail))
                    ((null? x*) (fail))
                    ((equal? (car y*) (car x*))
                     (iter (cdr y*) (cdr x*)))
                    (else (fail)))))
          (let iter ((y* '()) (x* x*))
            (succ x* (ext-dict id y* dict)
                  (lambda ()
                    (if (null? x*)
                        (fail)
                        (iter (attach y* (car x*))
                              (cdr x*))))))))))
(define (attach l x)
  (append l (list x)))
;<pattern> ::= <const>
;           |  <var>
;           |  (list <pat>*)
;<pat> ::= <const>
;       |  <var>
;       |  <seg-var>
;       |  (list <pat>*)
(define (compile-pattern p)
  (define (Pattern p)
    (if (const? p)
        (Const p)
        (case (car p)
          ((?) (Var (var-id p)))
          ((list)
           (apply List (map Pat (cdr p)))))))
  (define (Pat p)
    (if (const? p)
        (Const p)
        (case (car p)
          ((?) (Var (var-id p)))
          ((??) (Seg-var (var-id p)))
          ((list)
           (apply List (map Pat (cdr p)))))))
  (Pattern p))

向量处理

(define (vector-copy v)
  (define l (vector-length v))
  (define u (make-vector l))
  (let iter ((i 0))
    (if (= i l)
        u
        (begin
          (vector-set! u i (vector-ref v i))
          (iter (+ i 1))))))
(define (vector-swap! v i j)
  (define t (vector-ref v i))
  (vector-set! v i (vector-ref v j))
  (vector-set! v j t))
(define (build-vector l p)
  (define v (make-vector l))
  (let iter ((i 0))
    (if (= i l)
        v
        (begin
          (vector-set! v i (p i))
          (iter (+ i 1))))))
(define (vector-map p v)
  (define l (vector-length v))
  (define u (make-vector l))
  (let iter ((i 0))
    (if (= i l)
        u
        (begin
          (vector-set! u i (p (vector-ref v i)))
          (iter (+ i 1))))))
(define (vector-map! p v)
  (define l (vector-length v))
  (let iter ((i 0))
    (unless (= i l)
      (vector-set! v i (p (vector-ref v i)))
      (iter (+ i 1)))))
(define (vector-for-each p v)
  (define l (vector-length v))
  (let iter ((i 0))
    (unless (= i l)
      (p (vector-ref v i))
      (iter (+ i 1)))))