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 в Emacs, я получаю следующий результат:

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

Но когда я lein uberjar и запустить полученный jar file, я получаю ошибку:

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».

Для иллюстрации: если я оцениваю свой код в моем РЕПЛ и выполнить его, он помещает меня в contact-form.core имен, как и следовало ожидать, поскольку (ns 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=> 

Итак, указав вашу точку входа в main для автономного выполнения uberjar (за пределами РЕПЛ), это эквивалентно вызову (contact-form.core/-main) из пространства имен по умолчанию в банке, который является clojure.core, потому что (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

Смежные вопросы