对以下函数进行Clojure arity-overload的示例(取自cookbook):
(defn argcount
([] 0) ; Zero arguments
([x] 1) ; One argument
([ x & args] (inc (count args)))) ; List of arguments
...使用一个似乎不允许较低arity函数的表单来简单地调用具有一些默认值的较高arity函数(这是Java中常见的习语)。 是否使用了其他一些特殊形式?
答案 0 :(得分:14)
通常情况下,使用更高阶函数和map
/ reduce
以不需要引用其他元素的方式来表达更高的arity参数是一种好方法。在这种情况下,它非常简单:
(defn argcount
([] 0)
([x] 1)
([x & args]
(reduce + 1 (map (constantly 1) args))))
注意表达式的一般形式是:
(reduce reducing-function arity-1-value (map mapping-function rest-of-args))
你不能以这种方式做所有事情,但这适用于大量的多参数函数。它还使用map
获得了懒惰的优点,所以你可以做一些疯狂的事情,比如将一千万个参数传递给函数而不用担心:
(apply argcount (take 10000000 (range)))
=> 10000000
在大多数其他语言中尝试一下,你的堆栈将是吐司: - )
答案 1 :(得分:3)
在下面的示例部分中,本地需要数字和精度。定义的函数使用默认值重载精度。
(def overloaded-division
(let [divide-with-precision
(fn [divisor dividend precision]
(with-precision precision (/ (bigdec divisor) (bigdec dividend))))]
(fn
;lower-arity calls higher with a default precision.
([divisor dividend] (divide-with-precision divisor dividend 10))
;if precision is supplied it is used.
([divisor dividend precision] (divide-with-precision divisor dividend precision)))
)
)
在较低级别调用时,应用默认值:
user=> (overloaded-division 3 7)
0.4285714286M
user=> (overloaded-division 3 7 40)
0.4285714285714285714285714285714285714286M