[Openmcl-devel] CLOS make-instance :around behaviour
pc at p-cos.net
Sun Oct 19 15:33:45 EDT 2008
On 19 Oct 2008, at 20:53, Bob Hutchison wrote:
> (This is all os x 10.5.5, and "Clozure Common Lisp Version 1.2-r10552
> 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
> (format t "make instance around...~%")
> (let ((pxo (call-next-method)))
> (format t " the instance is ~A~%" pxo)
> (setf (state pxo) "INITIALISED")
> (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"]
> #<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 126.96.36.199.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 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