The language Forth offers a "compile-time" escape mechanism where code can be executed immediately, while the compiler is running (not at run-time). You can include print statements, for example, to debug tricky syntax or type errors).
Does Clojure have anything similar? I am getting a compile-time IllegalArgumentException in one of my function calls and would like to add a compile-time print statement to determine the argument type ((.getClass)
).
Thanks.
UPDATE: Here is the complete defn
that is failing compilation:
(ns my.ns.name
(:gen-class
:main true)
(:use
[clojure.contrib.str-utils2 :only (join)])
(:import
[java.io PrintWriter]
[java.net URL]
[java.util.concurrent Executors]
[java.util.jar Manifest]
[org.apache.commons.cli CommandLine HelpFormatter Options Option ParseException PosixParser]))
(defn set-version
"Set the version variable to the build number."
[]
(def version
(-> (str "jar:" (.. my.ns.name (getProtectionDomain)
(getCodeSource)
(getLocation))
"!/META-INF/MANIFEST.MF")
(URL.)
(.openStream)
(Manifest.)
(.. getMainAttributes)
(.getValue "Build-number"))))
This defn
works:
(defn set-version
"Set the version variable to the build number."
[]
(println (str (.getClass my.ns.name)))
(def version
(-> (str "jar:" (-> my.ns.name (.getProtectionDomain)
(.getCodeSource)
(.getLocation))
"!/META-INF/MANIFEST.MF")
(URL.)
(.openStream)
(Manifest.)
(.. getMainAttributes)
(.getValue "Build-number"))))
Printing the class of things during compilation is pretty restricted to special cases. You will mostly get Symbols and Seqs. Only literals have a meaningful type during compilation. You can execute arbitrary code during compilation via macros.
(defmacro debug-type
[x]
(println (type x))
x)
However as I said: this will normally not be very helpful. And no: in general you cannot wrap x
in an eval
, eg. if x
is a symbol refering to a let-local.
EDIT: Update for updated question.
(def version
(-> (str "jar:" (-> *ns* (.getProtectionDomain)
(.getCodeSource)
(.getLocation))
"!/META-INF/MANIFEST.MF")
(URL.)
(.openStream)
(Manifest.)
(.getMainAttributes)
(.getValue "Build-number")))
Try this. There is no need for a function. def
inside defn
should ring alarm bells.