Я прихожу с этим:
(defn string->integer [str & [base]] (Integer/parseInt str (if (nil? base) 10 base))) (string->integer "10") (string->integer "FF" 16)
Но это должен быть лучший способ сделать это.
Я прихожу с этим:
(defn string->integer [str & [base]] (Integer/parseInt str (if (nil? base) 10 base))) (string->integer "10") (string->integer "FF" 16)
Но это должен быть лучший способ сделать это.
Функция может иметь несколько сигнатур, если сигнатуры отличаются по arity. Вы можете использовать это для предоставления значений по умолчанию.
(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)))
Существует другой подход, который вы можете рассмотреть: partial. Это, возможно, более "функциональный" и более гибкий способ указания значений по умолчанию для функций.
Начните с создания (при необходимости) функции, которая имеет параметры (ы), которые вы хотите предоставить как по умолчанию (s), как ведущий параметр (ы):
(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