Clojure不断和地图功能

时间:2012-07-23 13:05:19

标签: clojure functional-programming

为什么这个Clojure代码:

user=> (map (constantly (println "Loop it.")) (range 0 3))

产生此输出:

Loop it.
(nil nil nil)

我希望它能三次打印“循环它”作为评估该功能三次的副作用。

3 个答案:

答案 0 :(得分:9)

constantly不会多次评估其参数。它是一个函数,而不是一个宏,所以在constantly运行之前,参数只被评估一次。所有constantly都会接受它的(已计算)参数,并返回一个函数,每次调用它时都会返回给定的值(不重新评估任何内容,因为正如我所说,参数已在{{1}之前评估过甚至跑步)。

如果您只想为范围中的每个元素调用constantly,则应将其作为映射函数传递而不是(println "Loop it")。请注意,您实际上必须将其作为函数传递,而不是计算表达式。

答案 1 :(得分:3)

您可以通过usig repeatedly和lambda表达式获得与您的意图接近的行为。

例如:

(repeatedly 3 #(println "Loop it"))

除非你在REPL,否则这需要被dorun或类似的包围。 repeatedly很懒惰。

答案 2 :(得分:3)

正如sepp2k正确地指出constantly是一个函数,所以它的参数只会被评估一次。

在这里实现目标的惯用方法是使用doseq

(doseq [i (range 0 3)]
  (println "Loop it."))

或者dotimes(在这种特殊情况下更简洁有效,因为你实际上并没有使用range生成的序列):

(dotimes [i 3]
  (println "Loop it."))

这两种解决方案都是非懒惰的,如果您只是为副作用运行一些代码,这可能就是您想要的。