Ced*_*tin 4 arguments function clojure
很多Clojure函数接受了不同数量的参数,我常常对文档以及它与我应该使用函数的方式有什么关系.
例如,(doc partial)返回:
([f arg1] [f arg1 arg2] [f arg1 arg2 arg3] [f arg1 arg2 arg3 & more])
Run Code Online (Sandbox Code Playgroud)
我的问题不是关于部分的,而是......
为什么arg1 arg2 arg3及更多而不是arg1及更多或arg1 arg2及更多或arg1 arg2 arg3 arg4 arg5 arg6 arg7 arg8及更多?
我在开玩笑随着最后一个,但是这是一个很现实的问题:是什么因素决定"argX"有多少人需要前放及更多?
以下答案是我的一个猜测:看一下partialshow us 的实现:
(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)))))
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,每次调用partial都会做同样的事情 - 即返回一个接受一些args的函数,并apply使用输入args和new args 调用输入函数.所以这确实可以写成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)))))))))
Run Code Online (Sandbox Code Playgroud)
Apply是一个核心函数,当给定不同数量的参数时,它的执行方式不同.这是出于性能原因而应用的优化.这是暴露部分(和其他此类函数)的不同元素的原因,因为代码的内部执行因不同的元素而不同.
我假设clojure/core团队认为暴露部分超出arg1 arg2 arg3及更多(即编写arg1 arg2 arg3 arg4及更多)并不美观,所以他们决定停在3 args以上.