2012-01-15 20 views
5

więc obecnie mam tego kodu:Clojure błąd oceny symbol

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

Po zrobić C-c C-k w Emacs, pojawia się następujący komunikat:

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

Ale kiedy zrobić lein uberjar i uruchom otrzymany plik jar, pojawia się błąd:

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 

Mam więc dwa pytania:

  1. Dlaczego uberjar nie działa dokładnie tak samo jak REPL?
  2. Co mogę zrobić, aby rozwiązać ten problem?

Odpowiedz

5

1. Dlaczego uberjar działa inaczej niż REPL?

Przyczyną błędu "NO_SOURCE_PATH" jest to, że nie jesteś obecnie w przestrzeni nazw, która zdefiniowała "foo".

Aby zilustrować: jeśli mam oceniać swój kod w moim REPL i wykonać ją, umieszcza mnie w przestrzeni nazw contact-form.core jak można się spodziewać, ponieważ (ns contact-form.core) jest oceniany przez REPL, ale jeśli mogę przejść do nazw user i nazywają -main I może produkować ten sam błąd:

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

Tak, określając swój punkt wejścia do main do samodzielnej realizacji uberjar (poza REPL), jest to równoznaczne z wywołaniem (contact-form.core/-main) z domyślnej przestrzeni nazw w swojej słoik, który jest clojure.core, ponieważ (ns contact-form.core) nie została oceniona. Rezultat: main może zostać wykonany przy użyciu w pełni kwalifikowanej (nazwanej) ścieżki do funkcji, ale żaden z symboli od contact-form.core nie jest dostępny w bieżącej domyślnej przestrzeni nazw.

2. fix

Rozwiązaniem byłoby wyraźnie włączyć do nazw pierwszy .:

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

'use' robi znacznie więcej niż tylko przełączyć nazw. Polecam '' (binding [* ns * (the-ns 'contact-form.core)] (some-func' foo)) '' – Chouser

+0

@chouser Świetnie! Uważaj mnie za zbudowanego, sir! :-) – Scott