11
votes

Test si un objet est un tableau primitif Java dans le clojure

Quelle est la meilleure façon de détecter si un objet est un tableau primitif Java dans le clojure?

La raison pour laquelle j'ai besoin de faire une manipulation spéciale pour les tableaux primitifs, ce qui pourrait ressembler à quelque chose comme: P>

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


1 commentaires

Je ne sais pas ce que le code de la clojure serait, mais vous pouvez créer un tableau vide pour chaque type primitif, appelez getclass () sur ceux-ci et mettre en cache les résultats. L'objet de classe doit être identique pour chaque éventail de ce type primitif - vous comparez les cachees avec objet.getclass () . (getclass () ne devrait pas vraiment être un appel lent)


7 Réponses :


10
votes

Vous pouvez utiliser la réflexion une fois pour obtenir la classe du nom, cache ceci puis Comparez le reste à celui

(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


2 commentaires

Nice, comme l'idée de mettre en cache les classes de la matrice primitives. Bien que cela me frappe comme un peu loin que ceux-ci ne sont pas déjà définis quelque part en Java!


"[j" pour long s est encore plus attachant, n'est-ce pas? En outre, quiconque a proposé les supports d'ouverture inégalés dans .tostring valeurs de retour, à tout moment, j'apprends leur nom, mon pitchfork sera prêt. Il brise Paredit pour moi tout le temps, sans parler L'effet sur ma psyche . (Remplacement de PRINT-METHODE pour tous les cas pertinents peut être réalisable ou non - mon sentiment d'intestin en cours est pas .)



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

1 commentaires

4
votes

ou ancien instance : xxx


2 commentaires

Quel alias utilisez-vous pour rt ? Vous voulez dire (classe / forname "[b") non?


@Davidjames rt est clojure.lang.rt.



5
votes

Comme indiqué par Arthur Ulfeldt, vous pouvez utiliser Classe / FORNAME , par exemple, comme ici: xxx

Si vous souhaitez éviter les chaînes magiques comme "[B" Lors de la mise en cache des classes, vous pouvez appliquer class à un objet de tableau existant: xxx


1 commentaires

Même plus simple: (classe d'octet-arrare-classe (classe (byte-array 0))) . (Pas de soulignement non plus!)



6
votes

Pour vérifier un tableau d'octets sans utiliser de réflexion, vous pouvez le faire:

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


0 commentaires

3
votes

accessoires à toutes les autres réponses. Ici, c'est comme une doublure: xxx

pour d'autres primitives, reportez-vous à http://docs.oracle.com/javase/7/docs/api/java/lang/class.html#getName%28%29 (ou la spécification Java). Ou faites simplement ce que Gerrit suggère avec (type (xyz-array 0)) . Spécifiquement, vous pouvez utiliser: xxx

car les performances ont été mentionnées, voici un petit résultat de référence d'exécution (heure (DoSimes [_ 500000] (byte-tableau? X) )) , et avec octe-array-class def'd xxx

instance? vs vs < Code> Type instance? gagne

partielle vs defn = defn gagne

mais l'une de ces approches ne sera probablement pas un goulot d'étranglement dans la performance. < / p>


0 commentaires

0
votes

Depuis Clojure 1.9, vous pouvez utiliser octets? octets? Doc Link


0 commentaires