I'm exploring some possibilities of Common Lisp syntax and I wanted to make an :around
method on make-instance
to return some arbitrary value in some cases. For sake of simplicity, let it be nil
, when I don't pass a needed argument. And it works, but not when calling in let:
(defclass foo ()
((bar :initarg := :initform '())))
(defmethod make-instance :around ((type (eql 'foo)) &key =)
(if (not =) nil (call-next-method)))
(print (make-instance 'foo)) ;; => NIL
(print (let ((x (make-instance 'foo))) x)) ;; => #<FOO {10037EEDF3}>
Can somebody explain this situation? Why is that so? Does SBCL try to be smart or is it actually a standard thing to be done? I know that I can work around it by using apply:
(print (let ((x (apply #'make-instance (list 'foo)))) x)) ;; => NIL
But I don't want to rely on this sort of workaround. Actually I can use a regular function for that and it's OK, but I want to understand why it works this way and if this behaviour can be disabled.
Looks like one of the optimization attempts for MAKE-INSTANCE
and constant class names in SBCL (-> CTOR)...
This seems to work:
(defmethod make-instance :around ((class (eql (find-class 'foo)))
&rest initargs
&key =
&allow-other-keys)
(declare (ignorable initargs))
(if (not =) nil (call-next-method)))
But probably useful to ask a SBCL expert or file a bug report...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With