2012-01-11 98 views
2

正如另一篇文章写的,我正在Clojure编写一个沉编译器。 对于我需要一个宏/功能,其接收符号作为参数,并且如果沉功能被绑定到其它返回功能,并且如果该符号被定义为Clojure的宏它应该返回宏,所以((function or) true false)应该给出相同的结果如(or true false)从Clojure的宏返回宏

我的宏目前的样子:

(defmacro kl/function [x] 
(cl/let [fn (symbol (cl/str (name x) "__fnPoF__"))] 
    (if (function? fn) `(eval ~fn) `(quote ~x)))) 

的“__fnPoF__”后缀是因为在沉双命名空间的存在。 (A值和功能可分配到相同的符号。)现在

我的问题是((function or) true false)计算结果为假,因为它的计算结果为('or true false)但是如果我离开了,而不是`(quote ~x)“引用”(x我得到的以下情况除外:

kl=> (function *) 
CompilerException java.lang.RuntimeException: Can't take value of a macro: #'kl/*, compiling:(NO_SOURCE_PATH:8) 

是否有人有一个想法如何解决这个问题

回答

3

你不能“回归”的宏,因为宏没有任何价值,但你可以让(函数或)扩大?符号或;然后通常的Clojure宏展开/评估机制w生病只是你想要的。所以,虽然我不知道沉是如何工作的,这似乎是一个简单的变化将是:

(defmacro kl/function [x] 
    (cl/let [fn (symbol (cl/str (name x) "__fnPoF__"))] 
    (if (function? fn) 
     `(eval ~fn) 
     x))) 

顺便说一句,这eval在我看来是一个灾难等待发生。我强烈怀疑eval对于你的目标是必要的。

+0

正如我上面写的,如果我取代''(报价X)''通过我x'得到'CompilerException了java.lang.RuntimeException:无法采取的宏观值:#'KL/*,编译:(NO_SOURCE_PATH:8)' – 2012-01-12 08:49:09

+0

@NameLess哇,这很有趣。它看起来像宏展开器看到'((function when)...)'没有宏作为它的第一个子表单,所以它放弃了宏展开。然后,当内在事物扩展到“时间”时,它不会恢复。我不知道你会如何处理这个问题。 – amalloy 2012-01-12 18:08:10