インスタンス生成を記録しておき後で条件を満すものを抽出したい - lisp-cookbook-ja/common-lisp GitHub Wiki

MOP c2mop ライブラリ

インスタンス生成を記録しておき後で条件を満すものを抽出したい

記録するためのメタクラスを定義し、そのスロットに記録します。

下記の例では、list-metaclassを定義し、list-metaclassをメタクラスとしたboxクラスのインスタンスが生成される度にメタクラスのスロット(all-instances)に生成されたインスタンスがpushされるようにします。

MOPの互換性のためCloser to MOPを利用しています。

;; メタクラス
(defclass list-metaclass (standard-class)
  ((all-instances :initform () :accessor class-all-instances)))

#-(or clisp allegro)
(defmethod c2mop:validate-superclass ((class list-metaclass) 
                                      (super standard-class))
  T)

(defmethod make-instance ((class list-metaclass) &rest initargs)
  (declare (ignore initargs))
  (let ((new-instance (call-next-method)))
    (push new-instance (class-all-instances class))
    new-instance))

;; list-metaclassをメタクラスとしたboxクラス
(defclass box () 
  ((color :initform 'white :initarg :color :accessor box-color)
   size)
  (:metaclass list-metaclass))
;; 動作
(make-instance 'box :color 'green)
(make-instance 'box :color 'black)
...

(mapc #'describe 
      (remove-if-not (lambda (box) (eq (box-color box) 'black))
		     (class-all-instances (find-class 'box))))

;-> #<BOX {100A12CB51}> is an instance of class #<LIST-METACLASS BOX>.
;   The following slots have :INSTANCE allocation:
;    COLOR    BLACK
;    SIZE     #<unbound slot>
;...
;=> (#<BOX {100A12CB51}> ...)