[Openmcl-devel] CLOS make-instance :around behaviour

Pascal Costanza pc at p-cos.net
Sun Oct 19 12:33:45 PDT 2008


On 19 Oct 2008, at 20:53, Bob Hutchison wrote:

> Hi,
>
> (This is all os x 10.5.5, and "Clozure Common Lisp Version 1.2-r10552
> (DarwinX8664)")
>
> Here is a small bit of lisp that illustrates, what I think, is
> peculiar behaviour:
>
> (defclass some-class ()
>   ((state :initform "NOT INITIALISED" :accessor state)))
>
> (defmethod print-object ((self some-class) out)
>     (print-unreadable-object (self out :type t :identity t)
>           (format out "[state ~S]"  (state self))))
>
> (defmethod make-instance :around ((class (eql 'some-class)) &rest
> initargs)
>   (format t "make instance around...~%")
>   (let ((pxo (call-next-method)))
>     (format t "  the instance is ~A~%" pxo)
>     (setf (state pxo) "INITIALISED")
>     pxo))
>
> (defun make-some-class()
>   (make-instance 'some-class))
>
>
> Now, from the repl:
>
> ? (make-instance 'some-class)
> make instance around...
>   the instance is #<SOME-CLASS [state "NOT INITIALISED"]
> #x300040D164DD>
> #<SOME-CLASS [state "INITIALISED"] #x300040D164DD>
> ? (make-some-class)
> #<SOME-CLASS [state "NOT INITIALISED"] #x300040D1647D>
>
>
> So, if you call make-instance directly from the repl, the make-
> instance :around method is called. If you call the function make-some-
> class it is not called. This is true for sbcl as well. However,
> lispworks and clisp call make-instance :around in both cases.

You're invoking undefined consequences.

See Section 11.1.2.1.2 in the HyperSpec, bullet 19: You're defining a  
method on a predefined generic function (make-instance) which is  
applicable when its only required argument is a direct instance of a  
standardized class (here the class 'symbol, of which 'some-class is an  
instance: (typep 'some-class 'symbol) => T).

Common Lisp implementations are allowed to take that restriction into  
account and, for example, compile away the call to make-instance and  
replace it with something more efficient in case the first argument is  
a constant symbol (for example).

If you really need :around methods on make-instance, consider defining  
your own metaclass using the CLOS MOP. But based on your example, I  
have the impression that an :after method on initialize-instance  
should be sufficient, which is generally preferable anyway...

Pascal

-- 
Lisp50: http://www.lisp50.org

Pascal Costanza, mailto:pc at p-cos.net, http://p-cos.net
Vrije Universiteit Brussel, Programming Technology Lab
Pleinlaan 2, B-1050 Brussel, Belgium










More information about the Openmcl-devel mailing list