2010-07-25 21 views
7

Estoy tratando de usar clojure en un compilador y, por lo tanto, necesito parametrizar las llamadas al deftype; sin embargo, tengo dificultades para llevar a cabo las sugerencias de tipo. Considere el siguiente código:Utilizando el tipo de definición Clojure como función parametrizada

(defn describe [x] 
    (let [fields (.getDeclaredFields x) 
     names (map #(.getName %) fields) 
     types (map #(.getType %) fields)] 
    (interleave types names))) 

(defn direct [] (deftype direct-type [^int x])) 
(defn indirect-helper [] (list ^int (symbol "x"))) 
(defn indirect [] (eval `(deftype ~(symbol "indirect-type") ~(indirect-helper)))) 

Y la siguiente sesión de la REPL:

Clojure 1.2.0-master-SNAPSHOT 
1:1 user=> #<Namespace dataclass> 
1:2 dataclass=> (direct) 
dataclass.direct-type 
1:3 dataclass=> (indirect) 
dataclass.indirect-type 
1:4 dataclass=> (describe direct-type) 
(int "x") 
1:5 dataclass=> (describe indirect-type) 
(java.lang.Object "x") 

en cuenta que la clase generada de tipo indirecto ha perdido la int^insinúa que tiene de tipo directo. ¿Cómo puedo obtener esos consejos para llevar a cabo?

Respuesta

7

Tendrá que cambiar indirect-helper leer

(defn indirect-helper [] [(with-meta (symbol "x") {:tag 'int})]) 

La razón es que ^int un análisis sintáctico como ^ seguido por int; ^, en Clojure 1.2, presenta los metadatos del lector (en 1.1 usaría #^, que aún funciona, pero está en desuso en 1.2). Por lo tanto ^int x en direct obtiene lectura en como clojure.lang.Symbol cuyo nombre es "x" y cuyos metadatos mapa es {:tag int} (con la int aquí mismo ser un símbolo). (El componente final de un símbolo - su espacio de nombres - es nil en este caso.)

En la versión de indirect-helper del texto de la pregunta ^int se apega a (symbol "x") - la lista que comprende el símbolo symbol y la cadena "x" (lo que significa en particular que (list ^int (symbol "x")) se evalúa a una lista de 1 elemento). Esta "sugerencia de tipo" se pierde una vez que se evalúa (symbol "x"). Para solucionar las cosas, se necesita una forma de adjuntar metadatos al símbolo real generado por (symbol "x").

Ahora, en este caso, el símbolo se genera en tiempo de ejecución, por lo que no puede usar los metadatos del lector para adjuntar la sugerencia de tipo. Introduzca with-meta, que se conecta metadatos en tiempo de ejecución (y con frecuencia es útil en la creación de macros por la misma razón, ya que es aquí) y el día se guarda:

user> (indirect) 
user.indirect-type 
user> (describe indirect-type) 
(int "x") 

(Por cierto, pensé deftype espera un vector de nombres de campos , pero aparentemente una lista también funciona ... Un vector aún es más idiomático.)

Cuestiones relacionadas