2012-01-15 55 views
5

所以我現在有這樣的代碼:Clojure的符號計算錯誤

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

我在Emacs做C-c C-k後,我得到下面的輸出:

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

但是當我做lein uberjar並運行結果jar文件,我得到一個錯誤:

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 

所以我有兩個問題:

  1. 爲什麼uberjar的功能與REPL的功能不完全相同?
  2. 我能做些什麼來解決這個問題?

回答

5

1.爲什麼uberjar的功能與REPL不同?

錯誤「NO_SOURCE_PATH」的原因是您目前不在定義'foo的命名空間中。

舉例說明:如果我在REPL評估你的代碼並執行它,它把我的contact-form.core命名空間中你所期望的,因爲(ns contact-form.core)由REPL評估,但如果我切換到user命名空間,並調用-main我能產生同樣的錯誤:

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=> 

所以,通過指定的入口點main爲獨立uberjar執行(REPL外),它相當於在你的罐子默認的命名空間是clojure.core調用(contact-form.core/-main),因爲(ns contact-form.core)尚未評估。結果:main可以通過函數的完全限定(名稱空間)路徑執行,但contact-form.core中的符號在當前默認名稱空間中不可用。

2.修復

的解決辦法是明確地切換到您的命名空間:首先

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

'use'確實遠不止切換的命名空間。我推薦''(binding [* ns *(the-ns'contact-form.core)](some-func'foo))'' – Chouser 2013-03-26 13:40:34

+0

@chouser太棒了!先生,請考慮我的建設! :-) – Scott 2013-03-26 21:23:40