在clojure中,是否有类似剂量的函数接收函数而不是身体

时间:2012-02-04 19:31:39

标签: clojure iteration

我想在集合上重复执行的副作用功能。 常见的方法是:

(defn my-func [x] (println x))
(doseq [x '(1 2 3) ]
       (my-func x))

x 变量有点麻烦。我更喜欢以下代码:

 ((comp doall map) my-func '(1 2 3))

你认为这是一个优雅的解决方案吗?

6 个答案:

答案 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!