2010-10-22 14 views
1

语言Forth提供了一个“编译时”转义机制,可以在编译器运行时(不在运行时)立即执行代码。例如,您可以包含打印语句,以调试棘手的语法或类型错误)。Clojure编译时​​转义机制

Clojure有类似的东西吗?我在我的一个函数调用中遇到了编译时IllegalArgumentException,并且希望添加一个编译时打印语句来确定参数类型((.getClass))。

谢谢。

UPDATE:这里是没有编制完整的defn

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

defn作品:

(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")))) 
+0

mmm在编译时?你什么时候编译源代码来生成jvm字节码? clojure没有其他编译时间。我认为这个异常只能在运行时导致public class IllegalArgumentException extends RuntimeException。要在运行时检查类,请在参数声明向量后插入(println(type arg)) – jneira 2010-10-22 11:53:59

+0

@jneira:我正在使用Maven构建项目。在AOT编译期间,肯定会发生**。 – Ralph 2010-10-22 12:08:53

+0

好吧,我想念那是在其运行时抛出异常的java编译器 – jneira 2010-10-22 12:31:23

回答

2

打印编译期间之类的东西是相当限于特殊情况。你将主要得到符号和Seqs。只有文字在编译过程中才有意义。您可以在编译期间通过宏执行任意代码。

(defmacro debug-type 
    [x] 
    (println (type x)) 
    x) 

但正如我所说:这通常不会很有帮助。和否:一般来说,您不能将x换成eval,例如。如果x是引用let-local的符号。

编辑:更新问题的更新。

(def version 
    (-> (str "jar:" (-> *ns* (.getProtectionDomain) 
          (.getCodeSource) 
          (.getLocation)) 
        "!/META-INF/MANIFEST.MF") 
    (URL.) 
    (.openStream) 
    (Manifest.) 
    (.getMainAttributes) 
    (.getValue "Build-number"))) 

试试这个。不需要功能。 def里面defn应该响铃警钟。

+0

@kotarak:我试图执行以下代码:'(.. my.ns.name(getProtectionDomain)(getCodeSource)(getLocation)) '并且在my.ns.name(“no getProtectionDomain方法”)上的AOT期间,我得到IllegalArgumentException。如果我将它更改为'( - > my.ns.name(.getProtectionDomain)(.getCodeSource)(.getLocation))'它可以工作。去搞清楚。 – Ralph 2010-10-22 12:12:55

+0

@Ralph:嗯..没有线索。你是否试过'* ns *'而不是实际的名字?你是否用'..'和' - >'清理了两次尝试之间的任何.class文件? – kotarak 2010-10-22 12:20:00

+0

@kotarak:更改为'* ns *'将错误移至运行时:-)。我在运行Maven之前清理了.class文件,并得到了相同的编译时错误。 – Ralph 2010-10-22 12:36:01