假设我有一个需要两个参数的函数,并且参数的顺序会影响结果。
是否可以将第一个参数传递给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)
答案 0 :(得分:8)
partial
只在左侧“填写”参数,因此如果您需要跳过参数,则必须使用fn
:
(def baz2 #(bar %1 arg2))
另请注意,comp
要求其所有参数都是函数,因此qux
和qux2
实际上是无意义的。他们应该是:
(def qux (comp str baz))
(def qux2 (comp str baz2))
一般来说,Clojure核心功能会将变量最有可能改变 last ,以使comp
和partial
更加自然。 (例如,集合参数在Clojure中几乎总是最后的,除了像into
之类的东西,把它放在第一位是有意义的。)当你设计自己的函数时,你应该坚持这个约定,这样你就可以编写你的函数更容易。
答案 1 :(得分:4)
Scheme SRFI 26有一个有用的宏cut
,用于插入这样的参数。
对于您减去bar
:
((cut bar <> 1) 2)
;=> 1
((comp str (cut - <> 1)) 2)
;=> "1"
<>
符号代表要填充的广告位。
在Clojure中自己实现cut
这是一项有趣的练习,但{@ 3}}来自@Baishampayan Ghose。
答案 2 :(得分: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是第一种)。
干杯!