2012-01-15 19 views
5

Vì vậy, tôi hiện đang có mã này:Clojure lỗi đánh giá biểu tượng

(ns contact-form.core 
    (:gen-class)) 

(def foo "Hello World!") 

(defn some-func [a-symbol] 
    (println (str a-symbol "'s value is: " (eval a-symbol)))) 

(defn -main [& args] 
    (some-func 'foo)) 

Sau khi tôi làm C-c C-k trong Emacs, tôi nhận được kết quả như sau:

contact-form.core> (-main) 
foo's value is: Hello World! 
nil 

Nhưng khi tôi làm lein uberjar và chạy kết quả tệp jar, tôi gặp lỗi:

Exception in thread "main" java.lang.RuntimeException: Unable to resolve symbol: foo in this context, compiling:(NO_SOURCE_PATH:0) 
    at clojure.lang.Compiler.analyze(Compiler.java:6235) 
    at clojure.lang.Compiler.analyze(Compiler.java:6177) 
    at clojure.lang.Compiler.eval(Compiler.java:6469) 
    at clojure.lang.Compiler.eval(Compiler.java:6431) 
    at clojure.core$eval.invoke(core.clj:2795) 
    at contact_form.core$some_func.invoke(core.clj:7) 
    at contact_form.core$_main.doInvoke(core.clj:10) 
    at clojure.lang.RestFn.invoke(RestFn.java:397) 
    at clojure.lang.AFn.applyToHelper(AFn.java:159) 
    at clojure.lang.RestFn.applyTo(RestFn.java:132) 
    at contact_form.core.main(Unknown Source) 
Caused by: java.lang.RuntimeException: Unable to resolve symbol: foo in this context 
    at clojure.lang.Util.runtimeException(Util.java:156) 
    at clojure.lang.Compiler.resolveIn(Compiler.java:6720) 
    at clojure.lang.Compiler.resolve(Compiler.java:6664) 
    at clojure.lang.Compiler.analyzeSymbol(Compiler.java:6625) 
    at clojure.lang.Compiler.analyze(Compiler.java:6198) 
    ... 10 more 

Vì vậy, tôi có hai câu hỏi:

  1. Tại sao uberjar không hoạt động chính xác giống như REPL?
  2. Tôi có thể làm gì để khắc phục sự cố này?

Trả lời

5

1. Tại sao hàm uberjar hoạt động khác với REPL?

Nguyên nhân gây ra lỗi "NO_SOURCE_PATH" là bạn hiện không có trong không gian tên được xác định 'foo.

Để minh họa: nếu tôi đánh giá mã của bạn trong REPL của tôi và thực hiện nó, nó đặt tôi trong không gian tên contact-form.core như bạn mong chờ bởi vì (ns contact-form.core) được đánh giá bởi REPL, nhưng nếu tôi chuyển sang không gian tên user và gọi -main tôi có thể sản xuất các lỗi tương tự:

contact-form.core=> (-main) 
foo's value is: Hello World! 
nil 
contact-form.core=> (ns user) 
nil 
user=> (contact-form.core/-main) 
CompilerException java.lang.RuntimeException: Unable to resolve symbol: foo in this context, compiling:(NO_SOURCE_PATH:120) 
user=> 

vì vậy, bằng cách xác định điểm vào của bạn để main để thực hiện uberjar độc lập (bên ngoài REPL), nó tương đương với gọi (contact-form.core/-main) từ không gian tên mặc định trong jar của bạn mà là clojure.core, bởi vì (ns contact-form.core) chưa được đánh giá. Kết quả: main có thể được thực thi với đường dẫn đầy đủ (không gian tên) đến hàm, nhưng không có biểu tượng nào trong số contact-form.core có sẵn trong không gian tên mặc định hiện tại.

2. Việc sửa chữa

Các giải pháp sẽ được rõ ràng chuyển sang không gian tên của bạn đầu tiên .:

(defn -main [& args] 
    (use 'contact-form.core) 
    (some-func 'foo)) 
+1

'use' còn có nhiều hơn chỉ cần chuyển đổi không gian tên. Tôi muốn giới thiệu '' (binding [* ns * (liên hệ-ns 'form.core)] (một số-func' foo)) '' – Chouser

+0

@chouser Tuyệt vời! Hãy xem xét tôi đã chỉnh sửa, thưa ngài! :-) – Scott