2016-12-26 50 views
7

鑑於該實施例中的代碼(從Reddit /r/lisp question):即使未設置,SBCL也會更改本地綁定函數對象的EQness?

(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*的值。

爲什麼?

+0

你也問過SBCL的郵件列表嗎? – coredump

+0

@coredump:不,還沒有 –

回答

2

看起來像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 
2

行爲方面變化的變量是否是特殊的:

(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(並指向新定義)。

相關問題