如何在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))) 

请注意,假设falsefalse两者都被认为是非值, (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的回答略有不同,因为参数的顺序已经由于本答复顶部的原因而被颠倒过来)