2012-01-15 13 views
5

Así que tengo actualmente este código:Clojure error de evaluación símbolo

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

Después de hacer C-c C-k en Emacs, me sale el siguiente resultado:

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

Pero cuando lo haga lein uberjar y ejecutar el resultante archivo jar, me sale un 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 

Tengo dos preguntas:

  1. ¿Por qué el uberjar no funciona exactamente igual que el REPL?
  2. ¿Qué puedo hacer para solucionar este problema?

Respuesta

5

1. ¿Por qué el uberjar funciona de manera diferente al REPL?

Una causa del error "NO_SOURCE_PATH" es que actualmente no se encuentra en el espacio de nombres que definió 'foo'.

Para ilustrar: si evalúo su código en mi REPL y ejecutarlo, me coloca en el contact-form.core espacio de nombres como era de esperar, porque (ns contact-form.core) se evalúa por el REPL, pero si me cambio a la user espacio de nombres y llamar -main I puede producir el mismo 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=> 

Así, especificando su punto de entrada a main para la ejecución uberjar independiente (fuera de la réplica), que es equivalente a llamar (contact-form.core/-main) del espacio de nombres por defecto en su frasco que es clojure.core, porque (ns contact-form.core) no ha sido evaluado. Resultado: main se puede ejecutar con una ruta de acceso totalmente calificada (espacio de nombres) a la función, pero ninguno de los símbolos de contact-form.core está disponible en el espacio de nombres predeterminado actual.

2. La solución

La solución sería cambiar de forma explícita a su espacio de nombres de primer .:

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

'use' hace mucho más que simplemente cambiar los espacios de nombres. Yo recomendaría '' (vinculante [* ns * (the-ns 'contact-form.core)] (some-func' foo)) '' – Chouser

+0

@chouser ¡Genial! Considérame edificado, señor! :-) – Scott

Cuestiones relacionadas