6

为什么这段 Clojure 代码:

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

产生这个输出:

Loop it.
(nil nil nil)

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

4

3 回答 3

9

constantly不会多次评估其论点。它是一个函数,而不是宏,因此在constantly运行之前,该参数只被评估一次。constantly所做的只是它接受它的(评估的)参数并返回一个函数,该函数在每次调用它时都返回给定的值(无需重新评估任何东西,因为正如我所说,参数甚至在运行之前就已经被评估了)constantly

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

于 2012-07-23T13:09:27.750 回答
3

您可以通过反复使用和 lambda 表达式获得接近您意图的行为。

例如:

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

除非您在 REPL,否则它需要被 adorun或类似名称包围。repeatedly是懒惰的。

于 2012-07-23T16:46:45.897 回答
3

正如 sepp2k 正确指出的那样constantly,它是一个函数,因此它的参数只会被评估一次。

实现您在这里所做的惯用方法是使用doseq

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

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

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

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

于 2012-07-23T17:00:01.517 回答