I have a problem constructing a DSL in Clojure. This is the concrete problem I have isolated from everything else.
Let's say we hava a simple macro:
user> (defmacro m1 [x] `'~x)
#'user/m1
it just returns the literal supplied user> (m1 toUpperCase) toUpperCase
if we call java method for object everything works as expected
user> (. "a" toUpperCase)
"A"
but if we substitute method name for macro call that returns the methodname
user> (. "a" (m1 toUpperCase))
; Evaluation aborted.
Unable to resolve symbol: toUpperCase in this context
I want to use some java library that has fluent interface like a().b().c(). This maps to Clojure as:
(.. obj method1 method2 method3....etc)
I want to create macros that substitute some parts of this chain so my code should be like:
(.. obj method1 macro1)
and that should expand to
(.. obj method1 method2 method3)
definline also doesn't help. I tried that also
The reason you're running into this problem is that the . special form does not evaluate its second argument (the symbol specifying the method or field) in the way you expect: it sees it as a call of the METHOD m1, with the ARGUMENT toUppercase. Because of that, you cannot generate the symbol for the method dynamically just as an argument to . (dot) - even if you use a macro to specify that argument.
A way to work around that is to include the . in your macro:
(defmacro m1 [x y] `(. ~x (~y)))
(m1 "a" toUppercase)
user> "A"
Note that you need to wrap parentheses around ~y to indicate you want to call a method instead of reading a field.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.