10

Clojure arity-overloading 函数的示例如下(取自cookbook):

(defn argcount
  ([] 0)                                ; Zero arguments
  ([x] 1)                               ; One argument
  ([ x &  args] (inc (count args))))    ; List of arguments

...使用一种似乎不允许较低数量的函数简单地调用具有一些默认值的较高数量的函数的形式(这是 Java 中的常见习语)。是否有其他特殊形式用于此?

4

2 回答 2

14

通常有一种很好的方式来表达更高的参数,而无需使用高阶函数和map/来引用其他参数reduce。在这种情况下,它非常简单:

(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))

您不能以这种方式做所有事情,但这适用于相当大比例的多参数函数。它还获得了使用 laziness 的优点map,所以你可以做一些疯狂的事情,比如将一千万个参数传递给一个函数,而不用担心:

(apply argcount (take 10000000 (range)))
=> 10000000

在大多数其他语言中尝试一下,你的堆栈将是 toast :-)

于 2013-02-10T02:54:20.847 回答
3

mikera 的回答很棒;我只是添加一个额外的方法。当重载函数需要默认值时,可以使用局部变量。

在下面的示例划分中,本地需要数字和精度。定义的函数使用默认值重载精度。

(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
于 2013-10-27T16:55:04.320 回答