如何在普通的lisp中获取类的所有实例?

时间:2016-10-03 13:21:47

标签: common-lisp clos

想象一下,我有一个班级:

(defclass person () ())

然后我做了一些实例:

(setf anna (make-instance 'person))    
(setf lisa (make-instance 'person))    

如何获取对象本身或分配给它们的符号名称?

我希望能够说出像(find-instances 'person)这样的内容,并获得(anna lisa)或至少(#<PERSON {100700E793}> #<PERSON {100700E793}>)之类的内容。

我搜索的内容相当于红宝石中的each_object

我非常希望能够在没有外部库的情况下完成它。

2 个答案:

答案 0 :(得分:6)

Common Lisp中没有内置的东西。

录制实例

为了查找类的所有实例,通常会使类在实例创建时记录实例。人们可以想象出各种机制。有时人们仍然希望实例被垃圾收集 - 然后需要某种非标准的数据结构来实现。我希望,有一些库可以为CLOS实例实现类似的东西。

迭代包的符号

如果您想知道某些或所有包中的哪些符号将CLOS实例作为值,您可以迭代它们(DO-SYMBOLSDO-ALL-SYMBOLS,...)并检查是否有符号值,如果该符号值是某个类的实例。

答案 1 :(得分:2)

据我所知,目前还没有便携式解决方案。如果您正在使用CCL,那么map-heap-objects可能会做,您正在寻找什么

(defclass foo () ())
(defvar *x* (make-instance 'foo))
(defvar *y* (list (make-instance 'foo)))

(defun find-instances (n class)
  (let ((buffer (make-array n :fill-pointer 0 :initial-element nil)))
    (ccl:map-heap-objects (lambda (x)
                            (when (and (typep x class) (< (fill-pointer buffer) n))
                              (setf (aref buffer (fill-pointer buffer)) x)
                              (incf (fill-pointer buffer)))))
     buffer))

(find-instances 2 'foo)
==> (#<FOO #x30200126F40D> #<FOO #x30200126634D>)

其他Common Lisp实现可能存在类似的解决方案。请注意,您必须初步预测遍历可能找到的实例数。原因是,(如Rainer Joswig所说),回调函数应该避免消耗。为了实现这一点,该实现预先分配缓冲区,并且最多收集多个实例。