2016-12-26 11 views
7

Biorąc pod uwagę ten przykładowy kod (ze Reddit /r/lisp question):SBCL zmienia EQness lokalnego obiektu funkcji granicy, nawet jeśli nie jest ustawiony?

(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*))) 

Przede ustanawia funkcję NEXT. Wewnątrz LET zachowujemy starą funkcję w OLD-NEXT. Następnie redefiniujemy globalną funkcję NEXT wewnątrz LET.

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

? (load "test.lisp") 

1 EQ? T 
2 EQ? T 

Tylko SBCL (SBCL 1.3.11) ma inny wynik:

* (load "test.lisp") 

1 EQ? T 
2 EQ? NIL 

Wartość lokalny zmienna old-next nie jest już wartością zmiennej globalnej eq.

Dlaczego ???

+0

Czy pytałeś również o listę mailingową SBCL? – coredump

+0

@coredump: nie, jeszcze nie –

Odpowiedz

2

Wygląda na to, że SBCL próbuje być sprytny i optymalizuje zmienną.

(defun foobar() 
    (print :foo)) 

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

Drukuje

:FOO 
:BAR 

Ale jeśli używasz SETF na zmienną,

(defun foobar() 
    (print :foo)) 

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

drukuje

:FOO 
:FOO 
2

Zachowanie zmienia czy zmienne są specjalne:

(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}> 

Pierwszy element odnosi się do najnowszej definicji, podczas gdy drugi, uzyskany ze zmiennej specjalnej, jest starą definicją, zgodnie z oczekiwaniami. Po usunięciu specjalnej deklaracji oba odniesienia mają wartość EQ (i wskazują nową definicję).

Powiązane problemy