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

(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 .然后我们重新定义全局函数 NEXT里面 LET .

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* 的值.

为什么???

请您参考如下方法:

无论变量是否特殊,行为都会发生变化:

(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(并指向新定义)。


评论关闭
IT干货网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!