Thank you Christophe! Your explanation if clear and useful, and your example works great.

I've been digging a little deeper and using structures as you recommend, which has led me to a similar question. I find that when using structures, SBCL similarly does not infer type when I use (slot-value ...), but if I use the corresponding accessor for the slot, everything works great. This isn't a problem for me (as I'll just use the accessors), but I was curious why this might be.

Here is another toy example, which uses a structure A and four methods x, y, z, and w (that all do the same thing differently):

(defstruct A
  (m-num 0 :type fixnum))

;; Optimizes great!
(defmethod x ((a A))
  (declare (optimize speed (safety 0)))
  (incf (a-m-num a)))

;; Also works great!
(defmethod y ((a A))
  (declare (optimize speed (safety 0)))
  (with-accessors ((m-num a-m-num)) a
    (incf m-num)))

;; Can't optimize the incf
(defmethod z ((a A))

  (declare (optimize speed (safety 0))) 
  (incf (slot-value a 'm-num)))

;; Also can't optimize (because macroexpands to slot-value)
(defmethod w ((a A))
  (declare (optimize speed (safety 0)))
  (with-slots (m-num) a
    (incf m-num)))


This example shows that using the accessor (a-m-num ...), or the similar (with-accessors ...) macro, optimizes great. However, using (slot-value ...) or the corresponding (with-slots ...) macro doesn't optimize the incf. Again, not a problem, but I'm curious.

Thanks again for all your useful help!

Best regards,
Steve




On Thu, Apr 24, 2014 at 1:41 AM, Christophe Rhodes <csr21@cantab.net> wrote:
Steve Levine <sjlevine@mit.edu> writes:

> I have a question about SBCL optimizations for slot types in classes. I've
> noticed that when using (with-slots ...) in a certain way, I seem to get a
> lot of "unable to optimize" notices. Here's a toy example:
>
> (defclass A ()
>   ((m_num
>     :type fixnum
>     :initform 2)))
>
>
> (defmethod f ((a A))
>   (with-slots (m_num) a
>     (incf m_num)))

The problem with SBCL acting on the information that the slot is
declared to be of type fixnum here, is that the class can be redefined
at any time, including changing any and all slot constraints, *without*
the method needing to be touched at all.  So if we compiled the method
function while baking in the fixnumness of the slot, we would have to
invalidate that function on incompatible class redefinition.

This isn't impossible, but it's hard.  Generally, CLOS has enough layers
of indirection that it's not easy to get maximum speed out of it; if
your design has settled down enough that redefinition is not necessary,
you could consider using structures for the things needing type
inference and speed.  Alternatively,
  (defmethod f ((a A))
    (let ((m (slot-value a 'm_num)))
      (declare (type fixnum m) (optimize speed (safety 0)))
      (incf m)
      (setf (slot-value a 'm_num) m)))
is inelegant but the fixnum addition should be fast.

Cheers,

Christophe