在Clojure中从宏返回宏

时间:2012-01-11 21:28:41

标签: macros clojure

正如另一篇文章所述,我正在Clojure中编写一个Shen编译器。 为此,我需要一个接收符号作为参数的宏/函数,如果Shen函数绑定到它,它返回函数,如果符号定义为Clojure宏,它应该返回宏,所以((function or) true false)应该给出与(or true false)相同的结果。

我的宏目前看起来像:

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

" __ fnPoF __"后缀是因为沉的双重命名空间。 (值和函数可以分配给相同的符号。)

我现在的问题是((function or) true false)评估为false,因为它的评估结果为('or true false),但如果我遗漏了"引用" (x代替`(quote ~x)我收到以下例外:

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

有人知道如何解决这个问题吗?

1 个答案:

答案 0 :(得分:3)

您不能“返回”宏,因为宏没有值。但你可以使(功能或)扩展到符号或;然后通常的Clojure宏扩展/评估机制将做你想要的。所以,虽然我不知道Shen是如何工作的,但似乎只是一个简单的改变:

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

顺便说一句,eval等待发生的灾难让我感到震惊。我强烈怀疑eval对你的目标是必要的。