まず、iotaを定義する。 簡潔にするため、オプション引数は使わない。
(defun iota (limit seed step) (if (> seed limit) nil (cons seed (iota limit (+ seed step) step))))
(> seed limit)
を一般化して、終了条件を指定できるよう変更する。
(defun func1 (pred seed step) (if (funcall pred seed) nil (cons seed (func1 pred (+ seed step) step))))
(+ seed step)
を一般化して、seedの変化を指定できるよう変更する。
(defun func2 (pred next-gen seed) (if (funcall pred seed) nil (cons seed (func2 pred next-gen (funcall next-gen seed)))))
最後に、mapcar関数と合成する。
(defun func3 (pred fn next-gen seed) (if (funcall pred seed) nil (cons (funcall fn seed) (func3 pred fn next-gen (funcall next-gen seed)))))
もっと単純に、こうしてもいい。
(defun func3 (pred fn next-gen seed) (mapcar fn (func2 pred next-gen seed)))
これでunfold関数の完成。
(defun unfold (p f g n) (if (funcall p n) nil (cons (funcall f n) (unfold p f g (funcall g n)))))