为什么这段 Clojure 代码:
user=> (map (constantly (println "Loop it.")) (range 0 3))
产生这个输出:
Loop it.
(nil nil nil)
我希望它打印三次“循环它”作为三次评估函数的副作用。
为什么这段 Clojure 代码:
user=> (map (constantly (println "Loop it.")) (range 0 3))
产生这个输出:
Loop it.
(nil nil nil)
我希望它打印三次“循环它”作为三次评估函数的副作用。
constantly
不会多次评估其论点。它是一个函数,而不是宏,因此在constantly
运行之前,该参数只被评估一次。constantly
所做的只是它接受它的(评估的)参数并返回一个函数,该函数在每次调用它时都返回给定的值(无需重新评估任何东西,因为正如我所说,参数甚至在运行之前就已经被评估了)constantly
。
如果您只想调用(println "Loop it")
范围内的每个元素,则应将其作为函数传递给 map 而不是constantly
. 请注意,您实际上必须将其作为函数传递,而不是评估表达式。
您可以通过反复使用和 lambda 表达式获得接近您意图的行为。
例如:
(repeatedly 3 #(println "Loop it"))
除非您在 REPL,否则它需要被 adorun
或类似名称包围。repeatedly
是懒惰的。
正如 sepp2k 正确指出的那样constantly
,它是一个函数,因此它的参数只会被评估一次。
实现您在这里所做的惯用方法是使用doseq
:
(doseq [i (range 0 3)]
(println "Loop it."))
或者dotimes
(在这种特殊情况下更简洁有效,因为您实际上并没有使用由 产生的序列range
):
(dotimes [i 3]
(println "Loop it."))
这两种解决方案都是非惰性的,如果您只是为副作用运行一些代码,这可能是您想要的。