2012-07-24 4 views
11

Powiedzmy mam specjalną var:eval formularz powinien ocenić daną formę w null środowiska leksykalnego, nie rozumiem co się spodziewać

(defvar x 20) 

potem wykonaj następujące czynności:

(let ((x 1)) (eval '(+ x 1)) 

który ocenia na 2.

Według CLHS, eval "Ocenia formę w bieżącym dynamicznym środowisku i środowisku leksykalnym o zerowym znaczeniu". Tak więc, spodziewałbym się uzyskać 21 zamiast 2.

Czy brakuje mi czegoś?

Teraz, jeśli nie mam wiążącą dla symbolu y dynamiczny, oceniając

(let ((y 1)) (eval '(+ y 1)) 

mam warunek: „Zmienna Y jest nieograniczony”, co ma sens, ponieważ nie ma wiążących dla y dynamiczny.

Uwaga: Używam SBCL 1.0.57

wdzięczni za pomoc z góry!

Odpowiedz

7

w przykładzie x jest special co oznacza, że ​​jest związana w dynamicznym środowisku

y jest nie specjalnego, więc jest związany w środowisku leksykalnym


tak w czasie pierwszych eval środowisk można przedstawić w następujący sposób:

dynamic environment: { x : 1 } -> { x : 20, ...other global variables... } -> nil 
lexical environment: nil 

symbol x jest wyjątkowy więc eval patrzy x w bieżącym dynamicznego środowiska w i stwierdza x = 1


zakładając, że został uruchomiony w tym samym Lisp jako ostatni przykład środowisko waszych drugi eval wygląda następująco:

dynamic environment: { x : 20, ...other global variables... } -> nil 
lexical environment: { y : 1 } -> nil 

symbol y jest nie szczególny tak eval patrzy y w leksykalnym środowiska zerowy - nie bieżące środowisko leksykalne - i nic nie znajdzie.

ma to sens, gdy zdajemy sobie sprawę, że seplenienie zazwyczaj jest kompilowane, a środowisko leksykalne można w niektórych przypadkach zoptymalizować do prostych instrukcji.

+0

To bardzo pomaga! Doceniam twoją pomoc bardzo! – Svarog

5

DEFVAR deklaruje swoje zmienne specjalne. Globalnie, wszędzie. Nie możesz tego łatwo usunąć.

To również powód, dla którego nigdy nie należy używać nazw zwyczajowych jak x, i, list jako nazw zmiennych dla DEFVAR. Zamiast tego upewnij się, że używasz *x*, , . W przeciwnym razie wszystkie zmienne, nawet lokalne, o tych nazwach zwyczajowych są deklarowane jako specjalne.

+0

Tak, używanie nauszników ze specjalnymi zmiennymi jest najlepszą praktyką wspieraną przez wszystkich (włączając mnie, ponieważ czyni to bardziej klarownym), ale nie autora książki "Let Over Lambda", aby wskazać dualność składni. W tym konkretnym przypadku chciałem sprawdzić, które wiązanie zostanie odebrane przez eval. Z tego co rozumiem, ponieważ X jest wyjątkowy, zmień istniejące "globalne" powiązanie X z określonym przez let's formula, i dlatego eval pobiera wartość 1 nowo związaną przez let. Proszę mnie poprawić, jeśli zrozumiałem to źle. – Svarog

+3

@Svarog: LET nie zmienia globalnego powiązania. Tworzy nowe lokalne powiązanie. W tym przypadku jest to wiązanie dynamiczne. Ponieważ X w analizowanym kodzie jest automatycznie zmienną specjalną (deklaracja DEFVAR działa), EVAL używa lokalnego wiązania dynamicznego. –

Powiązane problemy