<cl> (find-all 3 '(2 -3.0 1 2 3 -3 4 5)) (3) <cl> (find-all 3 '(2 -3.0 1 2 3 -3 4 5) :key #'abs) (3 -3) <cl> (find-all 3 '(2 -3.0 1 2 3 -3 4 5) :key #'abs :test #'equalp) (-3.0 3 -3)この関数find-allを作るためにはremoveを使うことができます.
<cl> (remove 3 '(2 -3.0 1 2 3 -3 4 5)) (2 -3.0 1 2 -3 4 5) <cl> (remove 3 '(2 -3.0 1 2 3 -3 4 5) :test #'equalp) (2 -3.0 1 2 -3 4 5) <cl> (remove 3 '(2 -3.0 1 2 3 -3 4 5) :key #'abs :test #'equalp) (2 1 2 4 5) <cl> (remove 3 '(2 -3.0 1 2 3 -3 4 5) :key #'abs :test #'(lambda (x y) (not (equalp x y)))) (-3.0 3 -3)以下のようにfind-allを定義することができます.
(defun find-all (item sequence &rest keyword-args &key (test #'eql) &allow-other-keys) (apply #'remove item sequence :test #'(lambda (&rest args) (not (apply test args))) keyword-args))ここで,&allow-other-keysというのは&keyによってキーワード引数として 宣言されている:test以外のキーワードを受け付けるためにつけなければ ならないものです.
(find-all 3 '(2 -3.0 1 2 3 -3 4 5) :key #'abs :test #'equalp)とした場合には,&rest引数である keyword-argsには
(:key #'abs :test #'equalp)が入っています.このkeyword-argsがapplyによってそのままremoveの引数として 渡されてしまいます.つまり,
(apply #'remove 3 '(2 -3.0 1 2 3 -3 4 5) :test #'(lambda (&rest args) (not (apply #'equalp args))) (list :key #'abs :test #'equalp))となって渡されたことになり,結局,
(remove 3 '(2 -3.0 1 2 3 -3 4 5) :test #'(lambda (&rest args) (not (apply #'equalp args))) :key #'abs :test #'equalp)と実行したことと同じになります.ここで,:testのキーワードが二つ渡され たことになりますが,最初のキーワードが優先されるようになっています.
<cl> (apply #'remove 3 '(2 -3.0 1 2 3 -3 4 5) :test #'(lambda (&rest args) (not (apply #'equalp args))) (list :key #'abs :test #'equalp)) (-3.0 3 -3) <cl> (remove 3 '(2 -3.0 1 2 3 -3 4 5) :test #'(lambda (&rest args) (not (apply #'equalp args))) :key #'abs :test #'equalp) (-3.0 3 -3)removeはシーケンスデータに対応した関数になっているため,find-allもシー ケンスデータに対応しています.しかし,シーケンスでない一般のリストデー タには適用できません.
<cl> (find-all #\3 "123456343") "333" <cl> (find-all 3 '(2 -3.0 1 2 (3) -3 4 5) :key #'abs :test #'equalp) Error: non-number to abs: (3) <cl> (find-all 3 '(2 -3.0 1 2 (3) -3 4 5) :test #'equalp) NIL