1

Imagine I have a class:

(defclass person () ())

And then I make some instances:

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

How can I get either the objects themselves or the symbol names they were assigned to?

I want to be able to say something like (find-instances 'person) and get something like (anna lisa) or at least (#<PERSON {100700E793}> #<PERSON {100700E793}>).

What I am search for is the equivalent of each_object in ruby.

I very much want to be able to do it without an external library.

Community
  • 1
  • 1
anonymous
  • 1,522
  • 14
  • 24
  • 1
    What are you trying to achieve here? – Dirk Oct 03 '16 at 13:40
  • TBH this is more of a debugging task rather than trying to implement something. I am trying to get the `hunchentoot` `*acceptor*` instance so I can stop a running server. However `hunchentoot:*acceptor*` gives me error as I have to ask for the acceptor in the context of a request. However being able to get the instance of a class seems handy and I think I can use it in the future too, for debugging, inspecting, etc... – anonymous Oct 03 '16 at 13:45
  • AFAIK, any solution for this would be implementation dependent. For CCL, see my answer below. I wasn't able to find something similar in the SBCL manual, and googeling for "lispworks heap walk" didn't produce any results either. – Dirk Oct 03 '16 at 13:54
  • @RainerJoswig it was just an example. I edited it. – anonymous Oct 03 '16 at 13:57
  • 1
    That's an old question: https://www.cs.cmu.edu/Groups/AI/html/faqs/lang/lisp/part5/faq-doc-4.html – Rainer Joswig Oct 03 '16 at 14:10
  • @Dirk I will wait a bit to see if someone will give a "portable" answer and if not, I will accept your answer. – anonymous Oct 03 '16 at 14:10

2 Answers2

7

There is nothing like that built-in in Common Lisp.

Recording instances

For finding all instances of a class, one would usually make it that the class records the instance upon instance creation. One can imagine various mechanisms for that. Sometimes one would still want instances to be garbage collected - then one needs some kind of non-standard weak datastructure to do so. I would expect, that there are some libraries which implement similar things for CLOS instances.

Iterating over symbols of a package

If you would like to know which symbols of some or all packages have CLOS instances as a value, you could iterate over them (DO-SYMBOLS, DO-ALL-SYMBOLS, ...) and check if the have a symbol value and if that symbol value is an instance of a certain class.

Rainer Joswig
  • 136,269
  • 10
  • 221
  • 346
2

There is no portable solution for this, as far as I know. If you are working on CCL, then map-heap-objects may do, what you are looking for

(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>)

Similar solutions may exist for other Common Lisp implementations. Note, that you have to have an initial hunch as to how many instances the traversal may find. The reason is, that (as Rainer Joswig noted), the callback function should avoid consing. In order to achieve that, this implementation allocates a buffer up-front, and collects at most that many instances.

Dirk
  • 30,623
  • 8
  • 82
  • 102