2017-10-10 8 views
0

Ich habe den folgenden Coderesolve verhält sich anders in REPL und -main

(ns clojure-noob.core 
    (:gen-class)) 

(defn -main [& args] 
    (defn A [x] (str x "a")) 
    (println (A "."))      ; .a 
    (println A)        ; some object 
    (println (symbol "A"))     ; just A 
    (println (resolve(symbol "A")))   ; nil 
    (println ((resolve(symbol "A")) ".")) ; nullpointer exception 
) 

Wenn ich die Zeilen (beginnend mit (defn A ...) eins nach dem anderen in repl eingeben, verhalten sie sich wie erwartet. Die letzte

(println ((resolve(symbol "A")) ".")) 

ruft A auf "." d. h. fügt den Buchstaben a hinzu. Aber die ganze Sache mit lein run in Leiningen aufgerufen gibt nil auf der vorletzten und eine Null-Zeiger-Ausnahme in der letzten Zeile, d. H. resolve löst nicht wie erwartet.

Was mache ich falsch? Was ist der Unterschied zwischen lein repl und lein run?

Antwort

1

Die kurze Antwort ist, dass Ihr aktuellen Namespace unterscheidet, wenn resolve in lein repl vs. lein run ausgewertet wird und resolve Arbeiten auf dem aktuellen Namespace. Die resolve docstring:

gleiche wie (ns-resolve * ns * Symbol) oder (ns-resolve * ns * & env Symbol)

*ns* ist eine Bindung an was auch immer die aktuellen Namensraum ist .

Sie können den Unterschied sehen, indem Sie (println "current ns is" *ns*) hinzufügen.

Mit ns-resolve und Leiten des Namespace explizit Code Arbeit in beiden Fällen machen:

(println (ns-resolve 'clojure-noob.core (symbol "A"))) 
(println ((ns-resolve 'clojure-noob.core (symbol "A")) ".")) 

Als Nebenwirkung, Sie in der Regel nicht sehen verschachteltedefn dh Ihre A Funktion außerhalb definiert werden/vor -main Funktion.

+0

Vielen Dank! Es funktioniert jetzt. – Rat62

+0

@ Rat62 Davon beantwortet Ihre Frage, sollten Sie es als die akzeptierte Antwort m markieren – Carcigenicate

Verwandte Themen