Clojure中的部分源代码说明

时间:2016-11-27 13:06:38

标签: clojure partial

我现在是clojure的初学者,试图在基本级别理解它。

我一直在尝试使用partial以及如何创建闭包,并且为了获得更深入的理解,我认为我应该通过执行(source 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] f)
  ([f arg1]
   (fn
     ([] (f arg1))
     ([x] (f arg1 x))
     ([x y] (f arg1 x y))
     ([x y z] (f arg1 x y z))
     ([x y z & args] (apply f arg1 x y z args))))
  ([f arg1 arg2]
   (fn
     ([] (f arg1 arg2))
     ([x] (f arg1 arg2 x))
     ([x y] (f arg1 arg2 x y))
     ([x y z] (f arg1 arg2 x y z))
     ([x y z & args] (apply f arg1 arg2 x y z args))))
  ([f arg1 arg2 arg3]
   (fn
     ([] (f arg1 arg2 arg3))
     ([x] (f arg1 arg2 arg3 x))
     ([x y] (f arg1 arg2 arg3 x y))
     ([x y z] (f arg1 arg2 arg3 x y z))
     ([x y z & args] (apply f arg1 arg2 arg3 x y z args))))
  ([f arg1 arg2 arg3 & more]
   (fn [& args] (apply f arg1 arg2 arg3 (concat more args)))))

我发现整个定义是多余的,因为我只会以“varargs”的方式编写它,即最后两行。

这是一个可读性功能还是我错过了一些基本的东西?

2 个答案:

答案 0 :(得分:4)

这不是可读性功能,而是性能问题。 Stuart Sierra在Clojure Don’ts: Optional Arguments with Varargs中解释了它:

  

变量arity函数调用必须分配一个序列来保存参数,然后通过apply。 Timothy Baldridge做了一个快速的performance comparison,表明对具有多个固定arities的函数的调用可以比变量arlar(varargs)函数调用快得多。

在该基准测试中,带有1个参数的varargs版本比具有1个arg的多个版本慢一个数量级,并且使用3个args,差异达到~2个数量级。

这并不是说根本不应该使用varargs:用varargs稀疏地调用fn可能不会影响性能,但是当从紧密循环中调用它时它可能会让你很难受。

答案 1 :(得分:1)

  

我发现整个定义是多余的,因为我只会写它   在" varargs"时尚,

你是对的。除了varargs定义之外的所有定义都是多余的。正如@nberger指出的那样,其他人可以提高绩效。你会发现很多这样的clojure核心:例如mapmaxcomp