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


Tags: 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}> ...)