Clojure评估宏

时间:2011-03-26 20:34:49

标签: macros clojure

我在使用Clojure构建DSL时遇到问题。这是我与其他一切事物隔离的具体问题。

假设我们有一个简单的宏:

user> (defmacro m1 [x] `'~x)
#'user/m1 

它只返回提供的文字     使用者名称> (m1 toUpperCase)     toUpperCase

如果我们为对象调用java方法,一切都按预期工作

user> (. "a" toUpperCase)
"A"

但是如果我们将方法名替换为返回方法名

的宏调用
user> (. "a" (m1 toUpperCase))

; Evaluation aborted.
Unable to resolve symbol: toUpperCase in this context

我想使用一些具有流畅界面的java库,如a()。b()。c()。 这映射到Clojure:

(.. obj method1 method2 method3....etc)

我想创建替换此链的某些部分的宏,因此我的代码应该是:

(.. obj method1 macro1)

那应该扩展到

(.. obj method1 method2 method3)
definline也没有帮助。我也试过了

1 个答案:

答案 0 :(得分:6)

你遇到这个问题的原因是。特殊形式不会以您期望的方式评估其第二个参数(指定方法或字段的符号):它将其视为METHOD m1的调用,其中ARGUMENT为Uppercase。因此,您不能动态生成方法的符号作为参数。 (点) - 即使您使用宏来指定该参数。

解决这个问题的方法是包括。在您的宏中:

 (defmacro m1 [x y] `(. ~x (~y)))
 (m1 "a" toUppercase)
 user> "A"

请注意,您需要在〜y周围括起括号以表示您想要调用方法而不是读取字段。