2012-01-14 27 views
7

Otrzymuję dziwne zachowanie podczas sprawdzania, czy symbol może zostać rozwiązany.Clojure: postanowienie deklaruje symbol

user=> ok 
CompilerException java.lang.RuntimeException: Unable to resolve symbol: ok in this context, compiling:(NO_SOURCE_PATH:0) 
user=> (resolve 'ok) 
nil 
user=> (if (resolve 'ok) "bla" (def ok 'ok)) 
"bla" 
user=> ok 
#<Unbound Unbound: #'user/ok> 
user=> (def ok 'ok) 
#'user/ok 
user=> ok 
ok 

Czy ktoś może mi powiedzieć, skąd to może pochodzić? Czy to zachowanie jest zamierzone?

+0

Jaką wersję Clojure używasz? Nie widzę tego na 1.2.1 – spacemanaki

+1

@ spacemanaki: Interesujące, właśnie to powtórzyłem w 1.2.1 i 1.3. Coś dziwnego dzieje się na pewno. –

+0

Mój błąd, drugie odniesienie do "ok" spowodowało wyjątek zamiast zwrócić obiekt '# ' i nie zwróciłem uwagi. Dla mnie, na 1.2.1 '(rozwiązać 'ok)' wewnątrz 'if' nie powoduje zadeklarowania' ok'. – spacemanaki

Odpowiedz

4

tworzy zmienną o nazwie okw czasie kompilacji. Kompilator skanuje cały formularz, aby go skompilować, odkrywa, że ​​zdefiniujesz zmienną o nazwie ok i utworzy ją dla ciebie (bez wiązania), zanim formularz zostanie faktycznie wykonany. Po wykonaniu formularza def, wartość środowiska wykonawczego tego wyrażenia zostanie przypisana do zmiennej user/ok. W twoim przykładzie tak się nie dzieje, ponieważ var został już utworzony, a gałąź if idzie w drugą stronę.

Używanie jako substytutu jest okropnym pomysłem, ponieważ testuje coś zupełnie innego: czy nazwany var (który musi istnieć) ma powiązanie, stałe lub wątkowo-lokalne.

+0

brzmi logicznie. Ale dlaczego '(jeśli (postanowienie 'x) x (def x' x))' daje 'CompilerException java.lang.RuntimeException: Nie można rozwiązać symbolu: x w tym kontekście, kompilując: (NO_SOURCE_PATH: 1)'? A może spróbuje ocenić x, zanim utworzy zmienną? –

1

Ponieważ używam go tylko wewnątrz makra Teraz używam go następująco

(defmacro bla [x] 
    (if (resolve x) x `(def ~x '~x))) 

A teraz to działa od def jest wewnątrz postaci cytowanego i oceniano po determinacji.