Как создать значение по умолчанию для аргумента функции в Clojure
Я пришел с этой:
(defn string->integer [str & [base]] (Integer/parseInt str (if (nil? base) 10 base))) (string->integer "10") (string->integer "FF" 16)
но это должен быть лучший способ, чтобы сделать это.
5 ответов:
функция может иметь несколько подписей, если подписи отличаются по арности. Вы можете использовать значения по умолчанию.
(defn string->integer ([s] (string->integer s 10)) ([s base] (Integer/parseInt s base)))обратите внимание, что при условии
falseиnilоба считаются не значениями,(if (nil? base) 10 base)можно сократить до(if base base 10), и далее(or base 10).
вы также можете уничтожить
restаргументы как карта с Clojure 1.2 [ ref]. Это позволяет задать имя и значения по умолчанию для аргументов функции:(defn string->integer [s & {:keys [base] :or {base 10}}] (Integer/parseInt s base))теперь вы можете звонить
(string->integer "11") => 11или
(string->integer "11" :base 8) => 9вы можете увидеть это в действии здесь:https://github.com/Raynes/clavatar/blob/master/src/clavatar/core.clj (например)
это решение ближе к дух оригинального решения, но незначительно чище
(defn string->integer [str & [base]] (Integer/parseInt str (or base 10)))A аналогичная картина что может быть удобно использовать
orв сочетании сlet(defn string->integer [str & [base]] (let [base (or base 10)] (Integer/parseInt str base)))хотя в этом случае более подробно, это может быть полезно, если вы хотите иметь значения по умолчанию зависят от других входных значений. Например, рассмотрим следующую функцию:
(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этот подход может быть легко расширен для работы с именованные аргументы (как и в решении М. Гиллиара), а также:
(defn exemplar [a & {:keys [b c]}] (let [b (or b 5) c (or c (* 7 b))] (println a b c)))или, используя еще больше фьюжн:
(defn exemplar [a & {:keys [b c] :or {b 5}}] (let [c (or c (* 7 b))] (println a b c)))
есть еще один подход, который вы можете рассмотреть:частичная функции. Это, возможно, более "функциональный" и более гибкий способ указать значения по умолчанию для функций.
начните с создания(при необходимости) функции, которая имеет параметр(Ы), который вы хотите предоставить по умолчанию в качестве ведущего параметра(ов):
(defn string->integer [base str] (Integer/parseInt str base))это делается потому, что версия Clojure
partialпозволяет указать значения "по умолчанию" только в порядке они появляются в определении функции. После того, как параметры были упорядочены по желанию, вы можете создать версию функции "по умолчанию" с помощьюpartialфункция:(partial string->integer 10)чтобы сделать эту функцию вызываемой несколько раз, вы можете поместить ее в var с помощью
def:(def decimal (partial string->integer 10)) (decimal "10") ;10вы также можете создать "локальное значение по умолчанию" с помощью
let:(let [hex (partial string->integer 16)] (* (hex "FF") (hex "AA"))) ;43350подход с частичной функцией имеет одно ключевое преимущество перед другими: потребитель функции все еще могут решать, что значение по умолчанию будет, а не производитель функции без необходимости изменять определение функции. Это проиллюстрировано в Примере с
hexгде я решил, что функция по умолчаниюdecimalэто не то, что я хочу.еще одно преимущество этого подхода заключается в том, что вы можете назначить функции по умолчанию другое имя (десятичное, шестнадцатеричное и т. д.), которое может быть больше описательная и / или другая область (var, local). Частичная функция также может быть смешана с некоторыми из подходов выше, если это необходимо:
(defn string->integer ([s] (string->integer s 10)) ([base s] (Integer/parseInt s base))) (def hex (partial string->integer 16))(обратите внимание, что это немного отличается от ответа Брайана, поскольку порядок параметров был изменен по причинам, указанным в верхней части этого ответа)
вы также можете посмотреть на
(fnil)https://clojuredocs.org/clojure.core/fnil