2010-10-25 5 views
14

Dans la réponse acceptée à une autre question, Setting Clojure "constants" at runtime, la fonction clojure constantly est utilisée.Quand utiliser `constamment` dans clojure, comment et quand ses arguments sont-ils évalués?

La définition de constantly ressemble à ceci:

(defn constantly 
    "Returns a function that takes any number of arguments and returns x." 
    {:added "1.0"} 
    [x] (fn [& args] x)) 

La chaîne doc dit ce qu'il fait, mais pas pourquoi on l'utiliserait.

Dans la réponse donnée à la question précédente est constamment utilisé comme suit:

(declare version) 

(defn -main 
    [& args] 
(alter-var-root #'version (constantly (-> ...))) 
(do-stuff)) 

Ainsi, la fonction renvoyée par est constamment évalué directement à son résultat. Je suis confus quant à la façon dont cela est utile. Je ne comprends probablement pas comment x serait évalué avec et sans être enveloppé dans `constamment '.

Quand devrais-je utiliser constantly et pourquoi est-ce nécessaire?

Répondre

10

La fonction constantly est utile lorsqu'une API attend une fonction et que vous voulez simplement une constante. C'est le cas dans l'exemple fourni dans la question.

La plupart des fonctions alter-* (dont alter-var-root) prennent une fonction pour permettre à l'appelant de modifier quelque chose en fonction de son ancienne valeur. Même si vous voulez juste que la nouvelle valeur soit 7 (sans tenir compte de l'ancienne valeur), vous devez toujours fournir une fonction (fournir seulement 7 entraînera une tentative d'évaluation, qui échouera). Donc, vous devez fournir une fonction qui retourne juste 7. (constantly 7) produit juste cette fonction, en épargnant l'effort nécessaire pour le définir.

Edit: Comme pour la deuxième partie de la question, constantly est une fonction ordinaire, donc son argument est évalué avant la construction de la fonction constante. Donc, (constantly @myref) renvoie toujours la valeur référencée par myref au moment où constantly a été appelée, même si elle est modifiée ultérieurement.