Fehler bei der Bewertung des Clojure-Symbols
-
28-10-2019 - |
Frage
Also habe ich derzeit diesen Code:
(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))
Nachdem ich in Emacs C-c C-k
erstellt habe, erhalte ich die folgende Ausgabe:
contact-form.core> (-main)
foo's value is: Hello World!
nil
Aber wenn ich lein uberjar
mache und die resultierende JAR-Datei ausführe, erhalte ich eine Fehlermeldung:
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
Ich habe also zwei Fragen:
- Warum funktioniert das Uberjar nicht genau so wie das REPL?
- Was kann ich tun, um dieses Problem zu beheben?
Lösung
1. Warum funktioniert Uberjar anders als REPL?
Eine Ursache für den Fehler "NO_SOURCE_PATH" ist, dass Sie sich derzeit nicht in dem Namespace befinden, der 'foo' definiert hat.
Zur Veranschaulichung: Wenn ich Ihren Code in meiner REPL auswerte und ausführe, wird er wie erwartet in den contact-form.core
-Namespace eingefügt, da (ns contact-form.core)
von der REPL ausgewertet wird. Wenn ich jedoch zum user
-Namespace wechsle und -main
aufrufe, kann ich dies tun den gleichen Fehler erzeugen:
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=>
Wenn Sie also Ihren Einstiegspunkt für main
für die eigenständige Ausführung von Uberjar (außerhalb der REPL) angeben, entspricht dies dem Aufruf von (contact-form.core/-main)
aus dem Standard-Namespace in Ihrem Jar, der clojure.core
ist, da (ns contact-form.core
nicht ausgewertet wurde. Ergebnis: main
kann mit einem vollständig qualifizierten (Namespace-) Pfad zur Funktion ausgeführt werden, aber keines der Symbole aus contact-form.core
ist im aktuellen Standard-Namespace verfügbar.
2. Das Update
Die Lösung wäre, zuerst explizit zu Ihrem Namespace zu wechseln:
(defn -main [& args]
(use 'contact-form.core)
(some-func 'foo))