7
votes

Le compilateur de Clojure évaluera-t-il automatiquement les expressions de littéraux à la compilation?

Ceci pourrait être une question idiote, mais:

Supposons qu'une expression ne dépend que de littéraux ou d'autres expressions qui ne dépendent qu'aux littéraux; le compilateur l'évaluera-t-il à la compilation?

Supposons que j'ai, xxx

B et A être évalué complètement à la compilation, de sorte que le L'utilisateur n'est pas affecté?

EDIT: Merci beaucoup, toutes les réponses ont été très utiles.

EDIT 6.6.2011: s'avère que si Vous essayez d'utiliser cette technique pour précomputer une très grande structure de données, il est facile de créer des fichiers de classe trop gros pour charger. Dans ces cas, vous souhaitez créer un fichier qui sera lu plutôt que dans un fichier de classe qui sera chargé. Les astuces macro décrits dans ces réponses ne doivent être appliquées que dans des situations où la valeur de retour n'est pas une structure de grande taille prohibitivement.

L'erreur lancée est: "Java.lang.classformatRor: Invalide Cet index de classe" Voir Ce fil pour la discussion d'une situation connexe.


0 commentaires

4 Réponses :


6
votes

Pas idiot du tout, je devais y penser et le tester.

Cela ne fonctionnera que si vous utilisez des macros au lieu de fonctions, car le corps d'une macro est évalué à la compilation / macroexpansion-time. Par exemple: xxx

puis A et b sont def d sur les valeurs renvoyées de l'évaluation préprocessé .


3 commentaires

Je pensais que les macros pourraient être un moyen de contourner cela. Trois questions: 1. Comment es-tu allé tester cela? (J'ai pensé à utiliser la fonction Ackerman et de voir quel point dans le processus que j'ai remarqué un ralentissement, mais je ne sais pas quelle est la façon la plus rigoureuse de faire cela est.) 2. Quand est évalué - à temps de chargement ? 3. Ne les cotes de Sytax ne vous inquiétez pas les uns les autres? Quoi qu'il en soit, merci beaucoup pour la réponse!


1) Je l'ai testé en utilisant une autre métrique, à savoir une fonction appelée println. Le message apparaît pendant la compilation mais n'apparaît pas lors du chargement de l'espace de noms compilé, on peut ainsi conclure que la fonction n'était pas exécutée au moment de l'exécution. 2) La valeur attribuée au VaR B est évaluée pendant la macroexpansion. 3) Oui. Il a été laissé par erreur d'une itération antérieure.


Pour être clair cependant, la réponse à votre question est "non". C'est juste qu'il existe des moyens d'atteindre un tel comportement quand vous le souhaitez.



3
votes

Dans votre exemple, les fonctions de consommation de temps sont appelées une seule fois, lorsque votre code est chargé.

Le compilateur de clojure n'essaie pas d'optimiser les expressions constantes, mais le compilateur Java Jit peut le faire dans certains cas.


0 commentaires

4
votes

Premièrement, il y a une raison assez importante pour laquelle les côtés de droite de def code> doivent être évalués au temps de chargement: ils peuvent dépendre de l'environnement en quelque sorte et dans le cas général, il est impossible dire si ils le font ou non. Prenez E.G.

(ns testdefs.core
  (:gen-class))

(defn take-your-time [t]
  (printf "Taking my time (%d)...\n" t)
  (Thread/sleep t))

(def a (take-your-time 5000))

(defmacro frozen-def [v e]
  (let [val (eval e)]
    `(def ~v ~val)))

(frozen-def b (take-your-time 5000))

(defn -main [& args]
  (println "Starting...")
  (println a)
  (println b))


2 commentaires

Désolé pour l'espacement étrange dans le code - ressemble à une certaine étrangeté de Markdown ou pas - si grand markdown-fu de ma part (la deuxième possibilité semble plus probable).


Je ne peux pas croire que j'ai oublié qu'il y a une fonction de sommeil.



0
votes

Pour les exemples donnés, les expressions sont évaluées au moment de la compilation / charge. def code> toujours em> évalue son deuxième argument. De formulaires spéciaux

(def symbol init?)


0 commentaires