wro*_*ame 5 clojure uberjar leiningen read-eval-print-loop clojure-1.3
所以我目前有这个代码:
(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))
Run Code Online (Sandbox Code Playgroud)
我这样做之后C-c C-k在Emacs,我得到以下的输出:
contact-form.core> (-main)
foo's value is: Hello World!
nil
Run Code Online (Sandbox Code Playgroud)
但是当我执行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
Run Code Online (Sandbox Code Playgroud)
所以我有两个问题:
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=>
Run Code Online (Sandbox Code Playgroud)
因此,通过指定main独立uberjar执行的入口点(在REPL之外),它等同于(contact-form.core/-main)从jar中的默认命名空间调用clojure.core,因为(ns contact-form.core)尚未被评估.结果:main可以使用函数的完全限定(命名空间)路径执行,但contact-form.core当前默认命名空间中没有任何符号可用.
2.修复
解决方案是首先明确切换到您的命名空间:
(defn -main [& args]
(use 'contact-form.core)
(some-func 'foo))
Run Code Online (Sandbox Code Playgroud)