如何在Clojure中为函数参数创build默认值
我来与这个:
(defn string-> integer [str&[base]] (Integer / parseInt str(if(nil?base)10 base))) (string - >整数“10”) (string - >整数“FF”16)
但是这一定是一个更好的方法。
如果签名不同,函数可以有多个签名。 您可以使用它来提供默认值。
(defn string->integer ([s] (string->integer s 10)) ([s base] (Integer/parseInt s base)))
请注意,假设false
和false
两者都被认为是非值, (if (nil? base) 10 base)
可以缩短为(if base base 10)
,或者进一步为(or base 10)
。
自从Clojure 1.2 [ ref ]之后,你也可以把rest
参数parsing为一张地图。 这可以让你命名和提供函数参数的默认值:
(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 (例如)
这个解决scheme更接近原来的解决scheme的精神 ,但边缘更清洁
(defn string->integer [str & [base]] (Integer/parseInt str (or base 10)))
类似的模式 ,可以方便地使用or
结合let
(defn string->integer [str & [base]] (let [base (or base 10)] (Integer/parseInt str base)))
虽然在这种情况下更详细,但如果您希望依赖于其他input值的默认值 ,则可能会非常有用。 例如,考虑以下function:
(defn exemplar [a & [bc]] (let [b (or b 5) c (or c (* 7 b))] ;; or whatever yer actual code might be... (println abc))) (exemplar 3) => 3 5 35
这种方法可以很容易地扩展到使用命名参数 (如M.Gilliar的解决scheme):
(defn exemplar [a & {:keys [bc]}] (let [b (or b 5) c (or c (* 7 b))] (println abc)))
或者使用更多的融合:
(defn exemplar [a & {:keys [bc] :or {b 5}}] (let [c (or c (* 7 b))] (println abc)))
还有另一种方法可能需要考虑: 部分函数。 这些可以说是更“function性”和更灵活的方式来指定函数的默认值。
首先创build(如果需要的话)一个函数,该函数将要提供的参数作为默认参数(s)作为主要参数:
(defn string->integer [base str] (Integer/parseInt str base))
这样做是因为Clojure的partial
版本允许您只按照它们出现在函数定义中的顺序提供“默认”值。 一旦参数按需要sorting,您就可以使用partial
函数创build函数的“默认”版本:
(partial string->integer 10)
为了使这个函数可以多次调用,你可以把它放在var使用def
:
(def decimal (partial string->integer 10)) (decimal "10") ;10
你也可以使用let
创build一个“本地默认”
(let [hex (partial string->integer 16)] (* (hex "FF") (hex "AA"))) ;43350
部分函数方法与其他方法相比具有一个关键优势:函数的使用者仍然可以决定什么是默认值而不是函数的生成器 , 而不需要修改函数定义 。 这是在hex
的例子中说明,我已经决定默认函数decimal
不是我想要的。
这种方法的另一个优点是你可以给默认函数分配一个不同的名字(十进制,hex等),这可能是更具描述性的和/或不同的范围(var,local)。 如果需要,部分function也可以与上面的一些方法混合:
(defn string->integer ([s] (string->integer s 10)) ([base s] (Integer/parseInt s base))) (def hex (partial string->integer 16))
(请注意,这与Brian的回答略有不同,因为参数的顺序已经由于本答复顶部的原因而被颠倒过来)
您也可以查看(fnil)
https://clojuredocs.org/clojure.core/fnil