147 votes

Comment créer de la valeur par défaut pour la fonction argument en Clojure

Je viens avec ceci:

(défn string->integer [str & [base]]
 (Integer/parseInt str (si (néant? de base) base 10)))

(string->integer "10")
(string->integer "FF" 16)

Mais il doit y avoir une meilleure façon de le faire.

193voto

Brian Carper Points 40078

Une fonction peut avoir plusieurs signatures si les signatures diffèrent dans arité. Vous pouvez l'utiliser pour fournir des valeurs par défaut.

(defn string->integer 
  ([s] (string->integer s 10))
  ([s base] (Integer/parseInt s base)))

Notez que, en supposant false et nil sont considérés comme des non-valeurs, (if (nil? base) 10 base) , pourrait être réduit de (if base base 10), ou à la suite d' (or base 10).

176voto

Matthew Gilliard Points 4360

Vous pouvez également se déstructurent rest arguments sous forme d'une carte depuis Clojure 1.2 [ref]. Cela permet de nommer et de fournir des valeurs par défaut pour les arguments de la fonction:

(defn string->integer [s & {:keys [base] :or {base 10}}]
    (Integer/parseInt s base))

Maintenant, vous pouvez appeler

(string->integer "11")
=> 11

ou

(string->integer "11" :base 8)
=> 9

Vous pouvez le voir en action ici: https://github.com/Raynes/clavatar/blob/master/src/clavatar/core.clj (pour exemple)

44voto

metasoarous Points 540

Cette solution est plus proche de l' esprit original de la solution, mais légèrement plus propre

(defn string->integer [str & [base]]
  (Integer/parseInt str (or base 10)))

Un modèle similaire qui peut être pratique utilise or combiné avec let

(defn string->integer [str & [base]]
  (let [base (or base 10)]
    (Integer/parseInt str base)))

Alors que dans ce cas, plus détaillé, il peut être utile si vous souhaitez avoir des valeurs par défaut dépendent d'autres valeurs d'entrée. Par exemple, considérons la fonction suivante:

(defn exemplar [a & [b c]]
  (let [b (or b 5)
        c (or c (* 7 b))]
    ;; or whatever yer actual code might be...
    (println a b c)))

(exemplar 3) => 3 5 35

Cette approche peut être facilement étendu à travailler avec des arguments nommés (comme dans M. Gilliar de la solution):

(defn exemplar [a & {:keys [b c]}]
  (let [b (or b 5)
        c (or c (* 7 b))]
    (println a b c)))

Ou même en utilisant plus d'une fusion:

(defn exemplar [a & {:keys [b c] :or {b 5}}]
  (let [c (or c (* 7 b))]
    (println a b c)))

12voto

optevo Points 537

Il existe une autre approche, vous pourriez envisager: partielle des fonctions. Ce sont sans doute plus "fonctionnelle" et de manière plus souple pour spécifier des valeurs par défaut pour les fonctions.

Commencez par créer (si nécessaire) une fonction qui a le paramètre(s) que vous souhaitez offrir en tant que par défaut(s) que le premier paramètre(s):

(defn string->integer [base str]
  (Integer/parseInt str base))

Ceci est fait parce que Clojure la version d' partial permet de vous fournir les "valeurs par défaut" que dans l'ordre où ils apparaissent dans la définition de la fonction. Une fois que les paramètres ont été commandés comme vous le souhaitez, vous pouvez ensuite créer un "défaut" de la version de la fonction à l'aide de l' partial fonction de:

(partial string->integer 10)

Afin de rendre cette fonction appelable à plusieurs reprises, vous pourriez le mettre dans une var à l'aide de def:

(def decimal (partial string->integer 10))
(decimal "10")
;10

Vous pouvez également créer un local "par défaut" à l'aide de let:

(let [hex (partial string->integer 16)]
  (* (hex "FF") (hex "AA")))
;43350

La fonction partielle approche a un avantage important sur les autres: la consommation de la fonction peut toujours décider que la valeur par défaut sera plutôt que le producteur de la fonction sans avoir à modifier la définition de la fonction. Ceci est illustré dans l'exemple avec hex où j'ai décidé que le défaut de la fonction decimal n'est pas ce que je veux.

Un autre avantage de cette approche est que vous pouvez affecter la fonction par défaut un nom différent (en décimal, hexadécimal, etc) qui peut être plus descriptif et/ou un champ d'application différent (var, local). La fonction partielle peut également être mélangé avec certaines des approches ci-dessus si vous le souhaitez:

(defn string->integer 
  ([s] (string->integer s 10))
  ([base s] (Integer/parseInt s base)))

(def hex (partial string->integer 16))

(Remarque c'est un peu différent de Brian de réponse quant à l'ordre des paramètres a été inversée pour les raisons indiquées en haut de cette réponse)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X