1
votes

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"))))
1
mmm in compile-time? when do you are aot compiling the source to generate jvm bytecode? there is no other compile time in clojure. i think that exception is only possible in runtime cause public class IllegalArgumentException extends RuntimeException. To check the class in runtime insert a (println (type arg)) after param declaration vector - jneira
@jneira: I am building the project using Maven. Is is definitely happening during AOT compilation. - Ralph
ok i miss that is the java compiler which is throwing the exception in its run time - jneira

1 Answers

2
votes

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.