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

을 내가 이맥스에 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에서 코드를 평가하고 그것을 실행하면, 그것은 (ns contact-form.core)가 REPL에 의해 평가되기 때문에 당신이 예상하는대로 contact-form.core 네임 스페이스에 나를 배치,하지만 난 user 네임 스페이스로 전환 한 경우 -main I 전화

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

따라서합니다 (REPL 외부) 독립 uberjar 실행을 위해 main에 엔트리 포인트를 지정하여,이 때문에, 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

+0

@chouser를 추천한다. 나는 교화 된 것으로 생각합니다! :-) – Scott