Ich möchte einen Clojure-Code ausführen, der von einer bestimmten var abhängt, aber nur, wenn diese Variable definiert ist. Als vereinfachtes Beispiel sollte der Körper der if
Form nur dann ausgeführt werden, wenn sym
definiert:Wie man ein Symbol nur verwendet, wenn es definiert ist
(if (resolve 'sym) (println sym))
Leider ist dies nicht funktioniert. Wenn sym
nicht definiert ist, versucht der Compiler immer noch, es zu lösen und wirft:
CompilerException java.lang.RuntimeException: Unable to resolve symbol: sym in this context
Aus der Lektüre Rich-Hickley Kommentar here, entnahm ich, dass dieses Verhalten zu Clojure der Nutzung von (meist) Single-Pass-Zusammenstellung beruht. Jedoch, so viel Sinn wie das macht, führt es offensichtlich in diesem Fall zu unerwünschtem Verhalten.
Ich kann indem das Symbol Auflösung, um das Problem bekommen zur Laufzeit geschehen:
(if (resolve 'sym) (println (deref (resolve 'sym))))
Aber dies ist ein unerwünschter Hack. Gibt es einen besseren Weg, oder ist es mit Clojures Read-Eval-Modell nicht möglich?
(Warum muss ich das tun? Ich in mehrere zusammensetzbare Profile definiert haben meine profiles.clj
. Einer von ihnen ist für vinyasa, die mir verschiedene Funktionen in die bequem zugänglich .
Namensraum injizieren können. Andere verschiedene andere Dienstprogramm laden Bibliotheken. In den Profilen für die anderen Utility-Bibliotheken, möchte ich Vinyasa verwenden, um die wichtigsten Funktionen zu injizieren, aber nur, wenn Vinyasa ist geladen. ich bin currently using eine Variation des Hack oben.)
Das ist sehr interessant! Es ist nicht sofort offensichtlich, was hier vor sich geht, aber wenn man einen Var als Funktion nennt, dereferenziert er sich selbst und ruft dann die Funktion auf, auf die er zeigt. Dies bedeutet insbesondere, dass Sie, wenn Sie diesen Trick für Vars verwenden möchten, die keine Funktionen sind, diese manuell dekompilieren müssen - aber Sie müssen nicht für Vars, die Funktionen sind. –
@RadonRosborough Ja, das stimmt genau. Sie können dies überprüfen, indem Sie den [Var-Quellcode] (https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Var.java#L374-L376) überprüfen. –