2012-01-14 20 views
7

Tôi nhận được một số hành vi lạ khi kiểm tra xem biểu tượng có thể được giải quyết hay không.Clojure: giải quyết biểu tượng tuyên bố

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 

Bất kỳ ai cũng có thể cho tôi biết điều này có thể đến từ đâu? Hành vi này có được dự định không?

+0

Bạn đang sử dụng phiên bản Clojure nào? Tôi không thấy điều này trên 1.2.1 – spacemanaki

+1

@spacemanaki: Thú vị, tôi chỉ sao chép điều này trong cả 1.2.1 và 1.3 Điều gì đó lạ chắc chắn đang xảy ra. –

+0

Sai lầm của tôi, tham chiếu thứ hai đến 'ok' dẫn đến một ngoại lệ thay vì trả về một đối tượng' # ', và tôi không chú ý. Đối với tôi, trên 1.2.1 '(giải quyết 'ok)' bên trong 'if' không dẫn đến' ok' được khai báo. – spacemanaki

Trả lời

4

(def ok "whatever") tạo biến có tên oktại thời gian biên dịch. Trình biên dịch quét toàn bộ biểu mẫu để biên dịch nó, phát hiện ra rằng bạn sẽ định nghĩa một var có tên là ok và tạo nó cho bạn (không có ràng buộc), trước khi biểu mẫu của bạn thực sự được thực thi. Khi biểu mẫu def được thực thi, giá trị thời gian chạy của biểu thức sẽ được gán cho var user/ok. Trong ví dụ của bạn, điều này không bao giờ xảy ra, bởi vì var đã được tạo và chi nhánh if theo cách khác.

Sử dụng bound? như là một thay thế là một ý tưởng khủng khiếp, vì nó kiểm tra một cái gì đó khá khác nhau: cho dù var được đặt tên (phải tồn tại) có một ràng buộc, hoặc vĩnh viễn hoặc thread-local.

+0

có vẻ hợp lý. Nhưng sau đó tại sao '(if (giải quyết 'x) x (def x' x))' yield 'CompilerException java.lang.RuntimeException: Không thể giải quyết biểu tượng: x trong ngữ cảnh này, biên dịch: (NO_SOURCE_PATH: 1)'? Hay anh ta cố gắng đánh giá x trước khi anh ta tạo biến? –

1

Vì tôi chỉ sử dụng nó bên trong một macro bây giờ tôi sử dụng nó như sau

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

Và bây giờ nó hoạt động kể từ khi def là bên trong các hình thức niêm yết và đánh giá sau quyết tâm.