2011-03-26 25 views
7

Tengo un problema al construir una DSL en Clojure. Este es el problema concreto que he aislado de todo lo demás.Evaluación Clojure de macros

Digamos que Hava una macro sencilla:

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

simplemente devuelve el literal suministrado de usuario> (m1 toUpperCase) toUpperCase

si llamamos método Java para el objeto todo funciona como se espera

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

pero si sustituimos el nombre del método para la llamada a la macro que devuelve el methodname

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

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

Quiero usar alguna biblioteca de Java que tenga una interfaz fluida como a(). B(). C(). Se correlaciona con Clojure como:

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

Quiero crear macros que sustituyen algunas partes de esta cadena por lo que mi código debe ser como:

(.. obj method1 macro1) 

y que debería ampliarse a

(.. obj method1 method2 method3) 

definición también no ayuda. Intenté eso también

Respuesta

6

La razón por la que te encuentras con este problema es que el. la forma especial no evalúa su segundo argumento (el símbolo que especifica el método o el campo) de la manera esperada: lo ve como una llamada del MÉTODO m1, con el ARGUMENTO en mayúsculas. Por eso, no se puede generar el símbolo para el método dinámicamente solo como un argumento para. (punto) - incluso si usa una macro para especificar ese argumento.

Una forma de evitar esto es incluir el. en su macro:

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

en cuenta que necesita para envolver paréntesis alrededor de ~ y para indicar que desea llamar a un método en lugar de leer un campo.

+0

muchas gracias! Esta es una buena sugerencia. –

Cuestiones relacionadas