Je suis quelques jours dans l'apprentissage de la gobelure et avoir des problèmes de dentition, donc je demande des conseils.
J'essaie de stocker une classe Java dans un Var de clojure et appelle ses méthodes statiques, mais ça ne marche pas. p>
Exemple: p> à partir de l'exception On dirait que l'exécution attend qu'un VaR contient un objet, il appelle donc .betclass () pour obtenir le classe et lève la méthode à l'aide de la réflexion. Dans ce cas, le Var contient déjà une classe, donc Y a-t-il un moyen de contourner cela, à part à écrire ma propre macro? p> Dans l'affaire Général, je voudrais avoir un objet ou une classe dans une variable et appelez les méthodes appropriées sur celui-ci - dactylographie de canard pour des méthodes statiques ainsi que par exemple des méthodes. P> Dans ce cas particulier, je voudrais juste un nom plus court pour EDIT: strong> p> Peut-être que je suis juste confus sur les conventions d'appel ici. Je pensais que le modèle Lisp (et par extension Clojure) était d'évaluer tous les arguments et d'appeler le premier élément de la liste en tant que fonction. P> dans ce cas Ainsi, la variable et le nom de la classe évaluent clairement à la même chose, mais ils ne peuvent toujours pas être appelés de la même manière. Ce qui se passe ici? P> Répondre à ma deuxième question (ce qui se passe ici), le CLOJURE DOC dit que P> Si le premier opérande est un symbole qui
résout à un nom de classe, l'accès
est considéré comme étant à un membre statique
de la classe nommée ... sinon il est
présumé être un membre d'instance p>
blockquote> http://clojure.org/java_terop sous "Le formulaire spécial de point" p> "La résolution d'un nom de classe" n'est apparemment pas la même chose que "l'évaluation de quelque chose qui se résout à un nom de classe", donc ce que j'essaie de faire ici n'est pas pris en charge par le formulaire spécial de point. P > p> .getclass () code> renvoie java.lang.class code> et la méthode de la recherche échoue évidemment. P> java.lang.reflect.modifier code>, un alias si vous le souhaitez. Je sais sur importer code>, mais cherche quelque chose de plus général, comme l'alias d'espace de noms de clojure mais pour les classes Java. Y a-t-il d'autres mécanismes pour faire cela? P> (= jmod java.lang.reflect. Modificateur) Code> retourne true et (. GetName jmod) code> et ( P>
3 Réponses :
Vous stockez avec succès la classe dans jmod, mais isprivate est une méthode statique de java.lang.reflect.modificateur, pas de java.lang.class.
Vous pouvez le faire avec réflexion: p> < Pré> xxx pré> p>
OK, ce serait l'option "écrire une macro", merci pour un exemple. Mais il n'y a pas de moyen standard d'appeler les méthodes statiques de modificateur dans cet exemple?
Eh bien, vous avez déjà trouvé (. Java.lang.reflect.modificateur iSprivate 1) qui va bien si vous connaissez le nom de la classe à l'avance. Ou vous pouvez utiliser la macro: (Application statique de défmacro [classe & args] `(. ~ Classe ~ @ args))
Je pense que la question sous-jacente est que ce que vous essayez de faire, nécessite une réflexion ou une connaissance du nom de la classe lors de la compilation. Il n'y a pas d'autre moyen de le faire sur la plate-forme Java autant que je sache.
(mise à jour: j'ai préparé quelque chose qui pourrait être acceptable comme une solution ... La réponse originale reste inférieure à une règle horizontale vers la fin du poteau.) em> Je viens d'écrire une macro pour activer ceci: p> L'idée est de créer un espace de noms à usage unique, d'importer la statique d'une classe donnée comme Vailles dans cet espace de noms, puis alias l'espace de noms à un nom utile. Convolé, mais ça marche! : -) p> Le code est ressemblant à ceci: p>
(use 'clojure.contrib.import-static)
(import-static clojure.lang.reflect.Modifier isPrivate)
(isPrivate 1)
; => false
(isPrivate 2)
; => true
Ah, gentil. Je ne savais pas qu'il y avait une telle chose, m'a sauvé la peine d'écrire le mien. Merci.
Je vous en prie. La réponse comprend maintenant une macro que j'ai écrite pour correspondre de plus près à vos besoins d'origine.
Soigné, j'aime ça. Dommage que je ne puisse pas donner plus d'un vote :) Cela ressemble à la meilleure solution, mais je laisserai la question ouverte pendant une journée ou donc de voir si d'autres veulent scintiller.
Heureuse d'entendre cela. :-) Notez qu'il est possible d'avoir un VaR appelé jmod code> à côté de l'alias code> jmod code> pour l'espace de noms à usage spécial, devrait-il être utile d'une manière utile. (Avec le VaR et l'adaptateur NS en place, (jmod / istatique 8) code> et (. GetMethods jmod) code> fonctionnerait.)
Ah, j'ai oublié de souligner que ce qui précède inclut utilisateur / importateur-all-all-all-all-all-all-all-all-all-all-all-all-statics Code> devrait être modifié pour ramasser importateur-all-statique code> de L'espace de nom correct (ou la macro pourrait être réécrit de manière plus intelligente de prendre en charge cela - peut-être que je le ferai plus tard).
Terminé. Avec la chance, il devrait être assez robuste maintenant.
En fait, je pense que je pensais à l'origine d'utiliser "adaptateur". Code> (et pas "adaptateur _" code>) comme partie initiale du nom de la gensym, afin de ne pas créer un seul- Espace de noms segment (comme celles-ci peuvent être problématiques).
Voici une macro inspirée des deux réponses précédentes qui gère des méthodes statiques sur les noms de classe et les variables avec des noms de classe ainsi que des méthodes d'instance sur les objets:
;; explicit class name, static method user=> (jcall java.lang.reflect.Modifier isPrivate 1) false ;; class name from var, static method user=> (jcall jmod isPrivate 1) false ;; works for objects and instance methods too user=> (jcall (Object.) toString) "java.lang.Object@3acca07b" ;; even with the object in a variable user=> (def myobj (Object.)) #'user/myobj user=> (jcall myobj toString) "java.lang.Object@4ccbb612" ;; but not for instance methods on classes user=> (jcall Object toString) java.lang.NoSuchFieldException: toString (NO_SOURCE_FILE:747)
Cela ne fonctionnera pas de manière fiable. Par exemple. Essayez de stocker la classe dans une Let locale au lieu d'un var. La bonne façon d'y aller consiste à utiliser la réflexion.