我在使用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也没有帮助。我也试过了
答案 0 :(得分:6)
你遇到这个问题的原因是。特殊形式不会以您期望的方式评估其第二个参数(指定方法或字段的符号):它将其视为METHOD m1的调用,其中ARGUMENT为Uppercase。因此,您不能动态生成方法的符号作为参数。 (点) - 即使您使用宏来指定该参数。
解决这个问题的方法是包括。在您的宏中:
(defmacro m1 [x y] `(. ~x (~y)))
(m1 "a" toUppercase)
user> "A"
请注意,您需要在〜y周围括起括号以表示您想要调用方法而不是读取字段。