为什么这个Clojure代码:
user=> (map (constantly (println "Loop it.")) (range 0 3))
产生此输出:
Loop it.
(nil nil nil)
我希望它能三次打印“循环它”作为评估该功能三次的副作用。
答案 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."))
这两种解决方案都是非懒惰的,如果您只是为副作用运行一些代码,这可能就是您想要的。