Hatena::Groupcadr

わだばLisperになる このページをアンテナに追加 RSSフィード

2004 | 12 |
2005 | 01 | 02 | 07 | 10 | 11 |
2006 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2007 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2008 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2009 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2010 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2011 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 11 |

2009-12-10

KMRCLを眺める (35) FILTER

| 23:50 | KMRCLを眺める (35) FILTER - わだばLisperになる を含むブックマーク はてなブックマーク - KMRCLを眺める (35) FILTER - わだばLisperになる

今回は、KMRCLのlists.lisp中からFILTERです。

filterは、関数型言語のユーティリティとしては割と有名なのではないでしょうか。

定義は

(defun filter (fn lst)
  "Filter a list by function, eliminate elements where fn returns nil"
  (let ((acc nil))
    (dolist (x lst (nreverse acc))
      (when (funcall fn x)
        (push x acc)))))

という感じですが、CLのREMOVE-IF-NOTの簡易版というところです。

(DEFVAR *LIST* '(1 2 3 4 NIL NIL 5 NIL 6 NIL 7))

(FILTER #'VALUES *LIST*)
;⇒ (1 2 3 4 5 6 7)

(REMOVE-IF-NOT #'VALUES *LIST*)
;⇒ (1 2 3 4 5 6 7)

REMOVE-IF-NOTは名前が少しひねくれているので、FILTERを定義したくなる気持ちも分からないではないです…。

一応、REMOVE-IF-NOTはsequence汎用ではあります。

(DEFVAR *VECTOR* #(1 2 3 4 NIL NIL 5 NIL 6 NIL 7))
(DEFVAR *STRING* "12345687890abcdef")

(REMOVE-IF-NOT #'VALUES *VECTOR*)
;⇒ #(1 2 3 4 5 6 7)

(REMOVE-IF-NOT #'DIGIT-CHAR-P *STRING*)
;⇒ "12345687890"