On Lisp復習

自分用

4章あたり

リストは効率が悪いからか,Lispではパフォーマンスもある程度意識してプログラミングされていくみたい。
ただ,とりあえず最初は単純なものを作れと書かれている。


リストの長さを比較する関数。
length関数で長さを取ると無駄な計算が生じるとのことで。
andとorの使い方がかっこいい。

CL-USER 3 >
(defun longer (x y)
  (labels ((compare (x y)
             (and (consp x)
                  (or (null y)
                      (compare (cdr x) (cdr y)) ))))
    (if (and (listp x) (listp y))
        (compare x y)
      (> (length x) (length y)) )))
LONGER

CL-USER 4 > (longer '(1 2 3 4) '(1 2 3))
T


filterの高速版と単純版。

CL-USER 5 > 
(defun filter (fn lst)
  (let (acc result)
    (dolist (x lst)
      (when (setq result (funcall fn x))
        (push result acc) ))
    (nreverse acc) ))
FILTER

CL-USER 6 > (filter #'(lambda (x)
                        (when (evenp x) (* x 10)) )
                    '(1 2 3 4 5 6 7 8) )
(20 40 60 80)

CL-USER 7 > 
(defun filter2 (fn lst)
  (delete nil (mapcar fn lst)) )
FILTER2

CL-USER 9 > (filter2 #'(lambda (x)
                         (when (evenp x) (* x 10)) )
                     '(1 2 3 4 5 6 7 8) )
(20 40 60 80)


groupの簡易版

CL-USER 1 > 
(defun group (lst n)
  (if (endp lst)
      nil
    (let ((rest (nthcdr n lst)))
      (cons (if (consp rest) (subseq lst 0 n) lst)
            (group rest n) ))))
GROUP

CL-USER 2 > (group '(1 1 1 1 1 1 1 1 1) 2)
((1 1) (1 1) (1 1) (1 1) (1))

末尾再帰を利用した高速版は眠いので省略。


以上のコードは記憶を頼りに書いたので(本当に覚えてるかの復習目的(だけど数箇所チラチラ見ちゃった。。。))書籍と完全一致してない部分もあるはず・・・。