The less-familiar parts of Lisp for beginners — allocate-instance

Continuing our series of posts on the more obscure commands of Lisp that beginners arriving from C++ might not have encountered and might not know when to use, we come to allocate-instance.

Think of this command as something that returns an object that hasn’t been constructed/initialized.  It’s an operation that has no counterpart in C++.  The object is built without filling in any of its slots.

Now, this may seem like a somewhat unnecessary function.  After all, why not just build the object with its slots initialized, and then overwrite the slots in a separate operation?  Well, there can be cases where allowing the object to be built normally, with make-instance, is undesirable.  A simple example might be the following:
 

;; A situation where you might prefer allocate-instance to
;; make-instance.


(let ((number-seq 0))

  (defun get-next-seq-id ()
    (incf number-seq)))

(defclass myclass ()
  ((id          :reader get-id
                :initform (get-next-seq-id))
   (data        :accessor get-data)))

(defun demonstrate ()
  (let ((obj1 (make-instance 'myclass))
        (obj2 (make-instance 'myclass))
        (obj3 (make-instance 'myclass)))

    (format t "ID of obj1= ~D~%" (get-id obj1))
    (format t "ID of obj2= ~D~%" (get-id obj2))
    (format t "ID of obj3= ~D~%" (get-id obj3))))

So, let’s say you’ve built this system, and you have some need to construct a new object which reuses an earlier ID.  Perhaps there was a bug that showed up only when a specific ID was passed into your hashing function, and you need to replicate the bug, but the object no longer exists.  As set up, a call to make-instance results in the next number in the sequence being allocated, and there’s no way to prevent the ID allocator from incrementing its internal state.

By using allocate-instance, you create a new object without calling its initform slot options.  Of course, you can imagine other contexts where avoiding the initform options are desirable, such as if the initform is very time-consuming, or if it invokes operations that affect the state in some way, such as opening network connections or disc files.

One place where I have seen allocate-instance used is in a generic object serializer in the cl-containers package.  There, objects can be passed to a method that writes them out to disc, and later they can be read back in.  To avoid complications during the read-in, the objects are allocated with allocate-instance and then the slots are individually restored from the disc file using a (setf (slot-value …) …) construct.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

反垃圾邮件 / Anti-spam question * Time limit is exhausted. Please reload CAPTCHA.