Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clojure symbol evaluation error

So I currently have this 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))

After I do C-c C-k in Emacs, I get the following output:

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

But when I do lein uberjar and run the resulting jar file, I get an error:

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

So I have two questions:

  1. Why does the uberjar not function exactly the same as the REPL?
  2. What can I do to fix this problem?
like image 482
wrongusername Avatar asked Jan 15 '12 10:01

wrongusername


People also ask

What are symbols in Clojure?

There may be some confusion here from the different usages of the term "symbol" in Common Lisp and in Clojure. In Common Lisp, a "symbol" is a location in memory, a place where data can be stored. The "value" of a symbol is the data stored at that location in memory. In Clojure, a "symbol" is just a name.

What is Clojure form?

Clojure (/ˈkloʊʒər/, like closure) is a dynamic and functional dialect of the Lisp programming language on the Java platform. Like other Lisp dialects, Clojure treats code as data and has a Lisp macro system.


1 Answers

1. Why does uberjar function differently to the REPL?

A cause of the error "NO_SOURCE_PATH" is that you are not presently in the namespace that defined 'foo.

To illustrate: if I evaluate your code in my REPL and execute it, it places me in the contact-form.core namespace as you would expect because (ns contact-form.core) is evaluated by the REPL, but if I switch to the user namespace and call -main I can produce the same error:

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

So, by specifying your entry point to main for standalone uberjar execution (outside the REPL), it is equivalent to calling (contact-form.core/-main) from the default namespace in your jar which is clojure.core, because (ns contact-form.core) has not been evaluated. Result: main can be executed with a fully qualified (namespaced) path to the function, but none of the symbols from contact-form.core are available in the current default namespace.

2. The fix

The solution would be to explicitly switch to your namespace first.:

(defn -main [& args]
  (use 'contact-form.core)
  (some-func 'foo))
like image 158
Scott Avatar answered Sep 30 '22 08:09

Scott