Tengo algunos días para aprender Clojure y tengo algunos problemas iniciales, por lo que estoy pidiendo consejo.Clojure vars y Java métodos estáticos
Estoy tratando de almacenar una clase Java en una var Clojure y llamar a sus métodos estáticos, pero no funciona.
Ejemplo:
user=> (. java.lang.reflect.Modifier isPrivate 1)
false
user=> (def jmod java.lang.reflect.Modifier)
#'user/jmod
user=> (. jmod isPrivate 1)
java.lang.IllegalArgumentException: No matching method found: isPrivate for class java.lang.Class (NO_SOURCE_FILE:0)
at clojure.lang.Compiler.eval(Compiler.java:4543)
Desde la excepción parece que el tiempo de ejecución espera una var para sostener un objeto, por lo que llama .getClass() para obtener la clase y mira hacia arriba el método que utiliza la reflexión. En este caso, la var ya contiene una clase, por lo que .getClass()
devuelve java.lang.Class
y la búsqueda del método obviamente falla.
¿Hay alguna forma de evitar esto, aparte de escribir mi propia macro?
En el caso general, me gustaría tener un objeto o una clase en una variable y llamar a los métodos apropiados en él - pato de tipeo para métodos estáticos, así como, por ejemplo, métodos.
En este caso específico, me gustaría un nombre más corto para java.lang.reflect.Modifier
, un alias si lo desea. Sé de import
, pero busco algo más general, como el alias del espacio de nombres Clojure, pero para las clases de Java. ¿Hay otros mecanismos para hacer esto?
Editar:
Tal vez estoy confundido acerca de las convenciones de llamada aquí. Pensé que el modelo Lisp (y por extensión, Clojure) debía evaluar todos los argumentos y llamar al primer elemento de la lista como una función.
En este caso (= jmod java.lang.reflect.Modifier)
devuelve verdadero, y (.getName jmod)
y (.getName java.lang.reflect.Modifier)
ambos devuelven la misma cadena.
Por lo que la variable y el nombre de clase claramente evalúan a la misma cosa, pero todavía no se pueden llamar de la misma manera. ¿Que está pasando aqui?
Editar 2
Responder a la segunda pregunta (lo que está sucediendo aquí), el doctor Clojure dice que
Si el primer operando es un símbolo que resuelve en un nombre de clase, el el acceso se considera que es un miembro estático de la clase nombrada ... De lo contrario, es supuestamente un miembro de instancia
http://clojure.org/java_interop en "The Dot forma especial"
"Resolución de un nombre de clase" aparentemente no es lo mismo que "la evaluación a algo que se resuelve en un nombre de clase", así que lo que estoy tratando de hacer aquí no es apoyado por la forma especial de punto.
Ah, lindo. No sabía que había tal cosa, me ahorró la molestia de escribir la mía. Gracias. –
De nada. La respuesta ahora incluye una macro que he escrito para que coincida con tus requisitos originales más de cerca. –
Limpio, me gusta. Lástima que no puedo dar más de un voto :) Esta parece la mejor solución, pero dejaré la pregunta abierta durante un día para ver si otros quieren entrar. –