即使未设置,SBCL也会更改本地绑定函数对象的EQness?

鉴于此示例代码(来自Reddit / r / lisp问题):

(defun next (pos)
  (nth (1+ pos)
       '(0 1 2 3 4 5 6 7 8 9 10)))

(defvar *next* (function next))

(let ((old-next #'next)
      (previous (make-hash-table)))
  (format t "~% 1 EQ? ~a" (eq old-next *next*))
  (defun next (pos)
    (or (gethash pos previous)
        (setf (gethash pos previous) (funcall old-next pos))))
  (format t "~% 2 EQ? ~a" (eq old-next *next*)))

以上建立一个函数NEXT 。 在LET内部,我们将旧功能保留在OLD-NEXT 。 然后我们重新定义LET内的全局函数NEXT

CCL / CMUCL / GCL / ECL / CLISP / LispWorks / ABCL:

? (load "test.lisp")

 1 EQ? T
 2 EQ? T

只有SBCL(SBCL 1.3.11)有不同的结果:

* (load "test.lisp")

 1 EQ? T
 2 EQ? NIL

局部变量old-next的值不再eq全局变量*next*

为什么???


看起来SBCL试图变得聪明并且优化变量。

(defun foobar ()
  (print :foo))

(let ((old #'foobar))
  (funcall old)
  (defun foobar ()
    (print :bar))
  (funcall old))

打印

:FOO 
:BAR 

但是如果你在变量上使用SETF

(defun foobar ()
  (print :foo))

(let ((old #'foobar))
  (funcall old)
  (setf old #'foobar)
  (defun foobar ()
    (print :bar))
  (funcall old))

它打印

:FOO 
:FOO 

行为会改变变量是否特殊:

(inspect
  (progn
    (defun next ())
    (let ((old #'next)
          (foo #'next))
      (declare (special foo))
      (defun next () :different)
      (list old foo))))

The object is a proper list of length 2.
0. 0: #<FUNCTION NEXT>
1. 1: #<FUNCTION NEXT {10037694EB}>

第一个元素是指最近的定义,而第二个元素是从特殊变量中获得的旧定义,如预期的那样。 当您删除特殊声明时,两个参考都是EQ(并指向新定义)。

链接地址: http://www.djcxy.com/p/94475.html

上一篇: SBCL changes EQness of a local bound function object, even though it is not set?

下一篇: Lifetime error using associated type of trait with lifetime parameter