2013-09-02 3 views
4

Considérons le code Clojure suivant:Clojure: def Java fonction statique

(defn space? [c] (Character/isWhitespace c)) 

Il est correct. Mais de toute évidence, cela est juste un autre nom et refactor dans le style inutile:

(def space? Character/isWhitespace) 

Mais j'obtiens l'erreur de compilation:

Caused by: java.lang.RuntimeException: Unable to find static field: isWhitespace 
in class java.lang.Character 

Pourquoi il ne peut pas le trouver? Il fonctionne parfaitement avec les fonctions Clojure:

(def wrap-space? space?) ; Compiles OK! 

Que se passe-t-il ici? Pourquoi def avec la fonction statique de Java ne fonctionne pas?

+0

Si vous voulez vraiment utiliser 'def', vous devez utiliser une fonction anonyme:' (espace def # (Personnage/isWhitespace%)?) '. Ceci est – Alex

+0

@ Alex Notation toujours pas libre de point que j'ai essayé d'atteindre. J'ai considéré cette variante aussi, merci. – demi

Répondre

7

Vos deux premières déclarations sont en fait pas équivalents. Quand vous dites ...

(def space? Character/isWhitespace) 

... Clojure tente de chercher un champ statique (pas de méthode) appelée isWhitespace dans java.lang.Character. Bien sûr, aucun champ n'existe, ce qui explique pourquoi vous obtenez l'erreur de compilation.

D'autres façons correctes de réécrire la déclaration suivante ...

(defn space? [c] (Character/isWhitespace c)) 

... seraient:

  • (def space? (fn [c] (Character/isWhitespace c)))
  • (defn space? [c] (. Character isWhitespace c))

Modifier

Juste pour ajouter, j'imagine que la raison Clojure permet (def wrap-space? space?) est parce qu'il n'y a aucune ambiguïté sur ce que space? est. Une méthode Java statique, d'autre part, pourrait être surchargée avec différents ensembles de paramètres, ou pourrait partager le même nom avec un champ statique. Par conséquent, pour aliaser une méthode Java statique, vous devez être explicite sur la méthode/champ que vous aliasez.

+0

La modification est particulièrement utile. Bien que, je pense qu'il est préférable d'avoir un message d'erreur sur l'ambiguïté. C'est plus clair. – demi

+1

En raison de la possibilité d'ambiguïté, il ne semble même pas une méthode moins en position d'appel. Bien que je sois d'accord, les erreurs de clojure en général sont souvent inutiles. Je pense que la différence sémantique est que toutes les fonctions Clojure sont des objets, alors que les méthodes sont attachés à un autre objet, et bien que nous aimons les choses à être de première classe, il n'y a aucune raison de traiter quelque chose comme première classe quand (comme une méthode java) il n'est pas de première classe et ne peut pas rester seul. – noisesmith