4

假设我有一个需要两个参数的函数,并且参数的顺序会影响结果。

是否可以将第一个参数传递给 partial 或 comp 函数,并将另一个参数传递给它,如下所示:

(defn bar [arg1 arg2] (- arg1 arg2))
(def baz (partial (bar arg1)))
(def qux (comp str (bar arg1)))

(baz arg2)
(qux arg2)

如果我想将 arg2 传递给函数,我可以做这样的事情吗?

(def baz2 (partial (bar _ arg2)))
(def qux2 (comp str (bar _ arg2)))

(baz arg1)
(qux arg1)
4

3 回答 3

9

partial仅在左侧“填充”参数,因此如果您需要跳过参数,则必须使用fn

(def baz2 #(bar %1 arg2))

还要注意,这comp要求它的所有参数都是函数,所以你的quxqux2实际上是胡说八道。他们应该是:

(def qux (comp str baz))
(def qux2 (comp str baz2))

一般来说,Clojure 核心函数会将最有可能发生变化的变量放在最后,以使组合comp更加partial自然。(例如,collection 参数在 Clojure 中几乎总是排在最后,除了into将它放在最前面有意义的地方。)当您设计自己的函数时,您应该坚持这个约定,这样您就可以更轻松地组合您的函数。

于 2013-02-28T16:49:02.543 回答
4

Scheme SRFI 26有一个有用的宏cut,用于像这样的开槽参数。

对于您的减法,用法就像这样bar

 ((cut bar <> 1) 2)
 ;=> 1
 ((comp str (cut - <> 1)) 2)
 ;=> "1"

其中<>符号表示要填充的插槽。

cut自己在 Clojure中实现 a 是一个有趣的练习,但这里是@Baishampayan Ghose 的一个端口。

于 2013-02-28T17:31:54.330 回答
2

这是我在repl中得到的:

user=> (defn bar [arg1 arg2] (- arg1 arg2))
#'user/bar
user=> (def baz (partial bar 5))
#'user/baz
user=> (def qux (comp str baz))
#'user/qux
user=> (baz 2)
3
user=> (qux 2)
"3"

这是我从你的第一个例子中得到的最接近的。

对于第二个例子,也许一个简单的 defn 比一个部分 def 更好:

user=> (defn baz2 [x] (bar x 5))
#'user/baz2
user=> (def qux2 (comp str baz2))
#'user/qux2
user=> (baz2 2)
-3
user=> (qux2 2)
"-3"

我建议您创建一个 repl 并自己尝试,这是发现我所知道的语言的第二个最佳方法(TDD 是第一个)。

干杯!

于 2013-02-28T16:13:54.497 回答