函数重载了不同数量的参数

时间:2012-05-26 19:06:25

标签: function clojure arguments

很多Clojure函数接受了不同数量的参数,我常常对文档以及它与我应该使用函数的方式有什么关系。

例如(doc partial)会返回:

([f arg1] [f arg1 arg2] [f arg1 arg2 arg3] [f arg1 arg2 arg3 & more])

我的问题不是关于部分而是......

为何选择 arg1 arg2 arg3&更多而不是 arg1&更多 arg1 arg2&更多 arg1 arg2 arg3 arg4 arg5 arg6 arg7 arg8&更多

我对最后一个人很滑稽,但这是一个非常现实的问题:是什么决定了在&之前需要放多少“argX”?更

2 个答案:

答案 0 :(得分:7)

以下答案是我的一个猜测:看看partial的实施情况向我们展示:

(defn partial
  "Takes a function f and fewer than the normal arguments to f, and
  returns a fn that takes a variable number of additional args. When
  called, the returned function calls f with args + additional args."
  {:added "1.0"
   :static true}
  ([f arg1]
   (fn [& args] (apply f arg1 args)))
  ([f arg1 arg2]
   (fn [& args] (apply f arg1 arg2 args)))
  ([f arg1 arg2 arg3]
   (fn [& args] (apply f arg1 arg2 arg3 args)))
  ([f arg1 arg2 arg3 & more]
   (fn [& args] (apply f arg1 arg2 arg3 (concat more args)))))

正如你所看到的,每次调用partial都会做同样的事情 - 即返回一个接受一些args的函数,并在输入函数上使用输入参数和新参数调用apply。所以这确实可以写成arg1 & more。但是等等,让我们看一下apply的实现:

(defn apply
 "Applies fn f to the argument list formed by prepending intervening arguments to args."
 {:added "1.0"
  :static true}
 ([^clojure.lang.IFn f args]
    (. f (applyTo (seq args))))
 ([^clojure.lang.IFn f x args]
    (. f (applyTo (list* x args))))
 ([^clojure.lang.IFn f x y args]
    (. f (applyTo (list* x y args))))
 ([^clojure.lang.IFn f x y z args]
    (. f (applyTo (list* x y z args))))
 ([^clojure.lang.IFn f a b c d & args]
    (. f (applyTo (cons a (cons b (cons c (cons d (spread args)))))))))

Apply是一个核心函数,当给定不同数量的参数时,它的执行方式不同。这是出于性能原因而应用的优化。这是暴露部分(和其他此类函数)的不同元素的原因,因为代码的内部执行因不同的元素而异。

我假设clojure /核心团队认为暴露部分超越arg1 arg2 arg3&更多(即写作arg1 arg2 arg3 arg4& more)不美观,所以他们决定停在3 args&更多。

答案 1 :(得分:3)

无论你认为什么是合理的。如果函数不是可变arity,则调用函数会更快,因此如果你没有超出它们的限制,它们会提供几个直接调用的函数。

我认为IFn中的函数有20个(?)args的限制,但我不知道编译器是否有解决方法。