The Little Schemer 四章

The Little Schemerの四章は、add1やsub1から自然数の+を定義したりする。数学的ですね。
数学的なのは良いんだけど、末尾再帰とかやってないからか、とにかく遅い。5の4乗(625)とか計算させるだけでxyzzyが20秒程度停止する。


プログラム書いてる途中にローカルな変数の名前の法則に気づいた。(遅い)
(a :atom)
(n :number)
(lat :lat)
(tup :tuple)
残念ながら気づくのが遅れたので、ほとんどこれに従わず書いてる。次回以降はこの辺も気にしながら書くよ。


以下プログラム羅列。

(defun add1 (x)
  (+ x 1))

(defun sub1 (x)
  (- x 1))

(defun zero? (x)
  (cond
   ((equal x 0) t)
   (t nil)))

(defun o2- (x y)
  (cond
   ((zero? y) x)
   (t (o- (sub1 x) (sub1 y)))))

(defun o- (x y)
  (cond
   ((zero? y) x)
   (t (sub1 (o- x (sub1 y))))))

(defun o+ (x y)
  (cond
   ((zero? y) x)
   (t (add1 (o+ x (sub1 y))))))

(defun addtup (a)
  (cond
   ((null a) 0)
   (t (o+ (car a) (addtup (cdr a))))))

(defun tup+ (a b)
  (cond
   ((null a) b)
   ((null b) a)
   (t (cons (+ (car a) (car b))
	    (tup+ (cdr a) (cdr b))))))

(defun ! (a)
  (not a))

(defun o* (x y)
  (cond
   ((equal 1 y) x)
   (t (o+ x (o* x (sub1 y))))))

(defun o< (a b)
  (cond
   ((and (zero? a) (! (zero? b))) t)
   ((zero? b) nil)
   (t (o< (sub1 a) (sub1 b)))))

(defun o> (a b)
  (cond
   ((and (zero? b) (! (zero? a))) t)
   ((zero? a) nil)
   (t (o> (sub1 a) (sub1 b)))))

(defun o** (x y)
  (cond
   ((equal 0 y) 1)
   (t (o* x (o** x (sub1 y))))))

(defun o/ (x y)
  (cond
   ((o< x y) 0)
   (t (add1 (o/ (o- x y) y)))))

(defun tuplen (x)
  (cond
   ((null x) 0)
   (t (add1 (tuplen (cdr x))))))

(defun pick (n lat)
  (cond
   ((or (zero? n) (null lat)) nil)
   ((one? n) (car lat))
   (t (pick (sub1 n) (cdr lat)))))

(defun one? (n)
  (cond
   ((zero? n) nil)
   ((zero? (sub1 n)) t)
   (t nil)))

(defun rempick (n lat)
  (cond
   ((or (zero? n) (null lat)) nil)
   ((one? n) (cdr lat))
   (t (cons (car lat)
	    (rempick (sub1 n) (cdr lat))))))

(defun no-nums (lat)
  (cond
   ((null lat) nil)
   ((numberp (car lat)) (no-nums (cdr lat)))
   (t (cons (car lat)
	    (no-nums (cdr lat))))))

(defun all-nums (lat)
  (cond
   ((null lat) nil)
   ((numberp (car lat))
    (cons (car lat)
	  (all-nums (cdr lat))))
   (t (all-nums (cdr lat)))))

(defun eqan? (a1 a2)
  (cond
   ((and (numberp a1) (numberp a2))
    (= a1 a2))
   ((or (numberp a1) (numberp a2))
    nil)
   (t (equal a1 a2))))

(defun occur (a lat)
  (cond
   ((null lat) 0)
   ((eqan? a (car lat)) (add1 (occur a (cdr lat))))
   (t (occur a (cdr lat)))))

m/^o(.)$/*1 な関数名は、元々$1*2という名前の関数を自分で定義したかったのでつけた名前です。
あとo2-は私が考えてた関数で、o-が The Little Schemerに載ってた関数。びみょーに違う。

*1:うわ、正規表現厨うぜえな。要は'o'のあとになんか一文字入るような名前

*2:うわ、正規表現厨うぜえな。要は'o'の後ろの一文字のこと