Clojure :: arity-overloaded函数互相调用

时间:2013-02-09 22:59:48

标签: clojure

对以下函数进行Clojure arity-overload的示例(取自cookbook):

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

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

2 个答案:

答案 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