繰返し処理 do (Common-Lisp)
『On Lisp』( http://www.asahi-net.or.jp/~kc7k-nd/onlisp_j.pdf )
を読んでたら、以下のようなコードが出てきて、5日間ほど悩んだ。
defun split-if (fn lst)
(let ((acc nil))
(do ((src lst (cdr src)))
((or (null src) (funcall fn (car src)))
(values (nreverse acc) src))
(push (car src) acc))))
CL-USER> (split-if #'(lambda (x) (> x 4))
'(1 2 3 4 5 6 7 8 9 10))
(1 2 3 4)
(5 6 7 8 9 10)
悩んだところというのは、次の箇所。
(do ((src lst (cdr src))) ... )
src という変数を lst で初期化しているのはわかるのだけど、
次の (cdr src) が何なのか、わからなかった。
これはつまり、更新処理だというのがわかったのは、以下のサイトの記述を見たから。
[Common Lisp] メモ: defconstant, boundp, do, dolist
この do の書き方を知らなかったので、メモしておく。
(do ((変数 初期値 更新方法))
((終了条件) (戻り値))
(繰り返し処理))
要するに、C言語などの for()文みたいなものかな。
ついでに、再帰で書き直してみた。
(defun split-if* (fn lst)
(let ((src lst))
(labels
((rec (src acc)
(if
(or (null src) (funcall fn (car src)))
(values (nreverse acc) src)
(rec (cdr src) (cons (car src) acc)))))
(rec src nil))))
カテゴリー: Lisp, memo
タグ: common-lisp, do, Lisp, On Lisp, 繰り返し
カウント: 118