温馨提示:本文翻译自stackoverflow.com,查看原文请点击:common lisp - Why does calling `make-instance` in `let` work differently?
clos common-lisp let sbcl

common lisp - 为什么在`let`中调用`make-instance`的工作方式不同?

发布于 2020-03-27 10:29:36

我正在探索Common Lisp语法的一些可能性,并且我想在某些情况下提供:around一种make-instance返回任意值方法为简单起见,nil当我不传递所需参数时,请设为它有效,但是在调用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}> 

有人可以解释这种情况吗?为什么呢?SBCL是否会尝试变得聪明,或者实际上是一项标准工作?我知道我可以使用apply解决它:

(print (let ((x (apply #'make-instance (list 'foo)))) x)) ;; => NIL

但是我不想依靠这种解决方法。实际上,我可以为此使用常规函数,这没关系,但是我想了解为什么它会以这种方式工作以及是否可以禁用此行为。

查看更多

查看更多

提问者
Bartek Lew
被浏览
67
Rainer Joswig 2019-06-16 18:43

看起来像是MAKE-INSTANCESBCL(-> CTOR)中的优化尝试和常量类名之一...

这似乎可行:

(defmethod make-instance :around ((class (eql (find-class 'foo)))
                                  &rest initargs
                                  &key =
                                  &allow-other-keys)
  (declare (ignorable initargs))
  (if (not =) nil (call-next-method)))

但是向SBCL专家咨询或提交错误报告可能很有用...