我想在集合上重复执行的副作用功能。 常见的方法是:
(defn my-func [x] (println x))
(doseq [x '(1 2 3) ]
(my-func x))
但 x 变量有点麻烦。我更喜欢以下代码:
((comp doall map) my-func '(1 2 3))
你认为这是一个优雅的解决方案吗?
答案 0 :(得分:6)
clojure.core/dorun
优于doall
,因为doall
将整个序列保存在内存中以便将其返回给您。 dorun
返回nil
,就像doseq
一样。要说语言核心“应该”提供像domap
这样的东西有点咄咄逼人 - 对于一种阻止突变和副作用的语言,Clojure已经有很多非常关闭的函数你想要什么,很容易结合。
答案 1 :(得分:4)
我其实很喜欢:
((comp dorun map) my-func '(1 2 3))
这是Clojure中“点自由风格”的一个很好的例子。高阶函数(comp dorun map)
在其他地方可能有用....你可以将它命名为“apply-to-sequence”或类似的东西。
你也可以使用以下(amalloy的建议),这也是无点的,可能有点更惯用:
(dorun (map my-func '(1 2 3)))
但请注意,使用map的两个解决方案都将构造一个中间(懒惰)序列来保存map函数的结果。这意味着少量的额外开销,所以如果你关心性能,那么我认为使用doseq的标准方法更好,即..
(doseq [x '(1 2 3)] (my-func x))
答案 2 :(得分:1)
使用doseq
。不要将懒惰序列与副作用结合起来。它可能会导致意外结果,例如使用分块序列。
答案 3 :(得分:0)
为什么不编写一个带函数和序列的函数,并通过doseq将函数应用于序列。
e.g。
user=> (defn doseqf [fun seq] (doseq [x seq] (fun x)))
#'user/doseqf
user=> (doseqf println '(1 2 3))
1
2
3
nil
答案 4 :(得分:0)
我与地图的简洁风格分享您的兴趣,我也不喜欢在这种情况下创建临时变量。
幸运的是,你可以自己轻松地编写这个功能:
(defn domap
"Implementation of Common Lisp `mapc`. It is like `map` except that the
results of applying function are not accumulated. The `colls` argument
is returned."
[f & colls]
(reduce (fn [_ args]
(apply f args))
nil (apply map list colls))
colls)
现在您有副作用的映射功能:
(domap println '(1 2 3))
答案 5 :(得分:0)
这里的大多数答案是在1.7版之前编写的,其中这样的功能被添加到Clojure中。
该功能为run!
。
(run! f coll)
相当于(dorun (map f coll))
。在Clojure 1.7及更高版本中首选run!
。