2012-02-01 6 views
10

¿Cuál es la mejor forma de detectar si un objeto es una matriz primitiva de Java en Clojure?Comprobando si un objeto es una matriz primitiva Java en Clojure

La razón por la que necesito esto es hacer una manipulación especial para las matrices primitivas, lo que podría ser algo como:

(if (byte-array? object) 
    (handle-byte-array object)) 

Está en una pieza bastante sensibles al rendimiento del código por lo que prefiere evitar la reflexión si en lo posible.

+1

No estoy seguro de cuál sería el código de Clojure, pero podría crear una matriz vacía para cada tipo primitivo, llamar a getClass() y codificar los resultados. El objeto Class debería ser el mismo para cada matriz de ese tipo primitivo: compararía los cacheados con 'object.getClass()'.(getClass() no debería ser realmente una llamada lenta) – millimoose

Respuesta

8

se puede utilizar la reflexión una vez para conseguir la clase del nombre, caché de esto y luego comparar el resto a la

(def array-of-ints-type (Class/forName "[I")) 
(def array-of-bytes-type (Class/forName "[B")) 
... 

(= (type (into-array Integer/TYPE [1 3 4])) array-of-ints-type) 
true 
+0

Agradable, como la idea de almacenar en caché las clases de matriz primitiva. ¡Aunque me parece un poco desagradable que estos no estén ya definidos en algún lugar de Java! – mikera

+0

y que se le ocurrió el nombre "[I" en ese ... –

+3

'" [J "' for 'long's es aún más entrañable, ¿no? Además, quien haya creado los inigualables corchetes de apertura en valores de retorno '.toString', cada vez que sepa su nombre, mi horquilla estará lista. Me rompe el crédito todo el tiempo, sin mencionar [el efecto en mi psique] (http://xkcd.com/859/). (Reemplazar 'print-method' para todos los casos relevantes puede o no ser factible - mi presentimiento actual es * no *.) –

7
(defn primitive-array? [o] 
    (let [c (class o)] 
    (and (.isArray c) 
     (.. c getComponentType isPrimitive)))) 

Para casos particulares, se puede usar algo como lo siguiente:

(defn long-array? [o] 
    (let [c (class o)] 
    (and (.isArray c) 
     (identical? (.getComponentType c) Long/TYPE)))) 
+0

Todos los secretos están al descubierto: http://docs.oracle.com/javase/6 /docs/api/java/lang/Class.html – Bill

4

O el viejo y simple instance?:

(instance? (RT/classForName "[B") thing) 
+0

¿Qué alias estás usando para 'RT'? ¿Quieres decir '(Class/forName" [B ")' right? –

+0

@DavidJames RT es clojure.lang.RT. – kotarak

4

Como se ha señalado por Arthur Ulfeldt, puede utilizar Class/forName, por ejemplo, como aquí:

(def byte_array_class (Class/forName "[B")) 

(defn byte-array? [arr] (instance? byte_array_class arr)) 

Si se quiere evitar cuerdas mágicas como "[B" al almacenamiento en caché de las clases, se puede aplicar class a una matriz existente objeto:

(def byte_array_class (class (byte-array []))) 
+1

Aún más simple: '(def byte-array-class (clase (byte-array 0)))'. (¡Sin guiones bajos tampoco!) –

5

para comprobar si hay una matriz de bytes sin el uso de la reflexión se puede hacer esto:

(def ^:const byte-array-type (type (byte-array 0))) 
(defn bytes? [x] (= (type x) byte-array-type)) 

No estoy seguro de por qué, pero puede incluso alinear el tipo de matriz de bytes con ^:const.

2

Apoya a todas las demás respuestas. Aquí es como una sola línea:

(def byte-array? (partial instance? (Class/forName "[B"))) 

Para otras primitivas, se refiere a http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#getName%28%29 (o la especificación de Java). O simplemente haz lo que sugiere Gerrit con (type (xyz-array 0)). En concreto se puede utilizar:

"[Z" boolean array 
"[B" byte array 
"[C" char array 
"[D" double array 
"[F" float array 
"[I" integer array 
"[J" long array 
"[S" short array 

Puesto que el rendimiento fue mencionado, aquí está un pequeño resultado del benchmark de correr (time (dotimes [_ 500000] (byte-array? x))), y con byte-array-class def'd

(def byte-array? (partial instance? (Class/forName "[B"))) 
78.518335 msecs 
(defn byte-array? [obj] (instance? byte-array-class obj)) 
34.879537 msecs 
(defn byte-array? [obj] (= (type obj) byte-array-class)) 
49.68781 msecs 

instance? vs = type ejemplo? gana

partial vs defn = defn gana

pero ninguno de estos enfoques es probable que no habrá un cuello de botella en el rendimiento.

Cuestiones relacionadas