Clojure: 区分 comp 和 partial 的参数

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)
3个回答

9

partial 只会在左侧“填充”参数,因此如果你需要跳过某些参数,你必须使用 fn

(def baz2 #(bar %1 arg2))

请注意,comp 要求其所有参数都是函数,因此你的 quxqux2 实际上是没有意义的。它们应该改为:
(def qux (comp str baz))
(def qux2 (comp str baz2))

通常情况下,Clojure核心函数会把最可能更改的变量放在最后,以使与comppartial的组合更加自然。(例如,在Clojure中,集合参数几乎总是放在最后,除了像into这样的情况,其中将其放在首位是有意义的。) 当你设计自己的函数时,应该遵循这个惯例,以便更轻松地组合你的函数。

感谢您告诉我们这个规定。 - leontalbot

4

Scheme SRFI 26提供了一个有用的宏cut,可以像这样槽参数。

对于减去bar,使用方式如下:

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

<>符号代表要填充的插槽。

实现Clojure中的cut功能是一个有趣的练习,但是@Baishampayan Ghose在这里提供了一个版本。


3

这是我在一个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比partial 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是第一)。

干杯!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接