2016-11-27 136 views
1

我是clojure的初学者,目前正试图在基本级别上理解它。在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))))) 

我觉得整个的定义是多余的,因为我只会把它写在“可变参数”方式,即在最后2行。

这是一个可读性功能还是我缺少一些基本的东西?

回答

4

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

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

在该基准中,可变参数版本1个参数是围绕大小比多元数版本1个ARG慢的顺序,并用3 ARGS的差上升到〜2个数量级。

这并不是说可变参数不应该被使用:稀疏地调用带可变参数的fn可能不会影响性能,但是当从紧密循环中调用它时它可能会打到你很难。

1

我觉得整个的定义是多余的,因为我只会写一个“可变参数”时尚 ,

你说得很对。除了可变参数定义都是多余的。正如@nberger指出的那样,其他人在那里提高性能。你会发现很多这样的clojure核心:如map,maxcomp