我现在是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”的方式编写它,即最后两行。
这是一个可读性功能还是我错过了一些基本的东西?
答案 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核心:例如map
,max
和comp
。