Clojure和Leiningen:为什么在这个例子中需要`doall`?

时间:2018-05-27 18:24:29

标签: clojure leiningen read-eval-print-loop

我目前正在使用Leiningen学习Clojure,我对doall运行此功能的要求感到困惑:

;; take a function (for my purposes, println for output formatting) and repeat it n times
(defn repeat [f n] (for [i (range n)] (f)))

(repeat println 2)在REPL会话中运行正常,但在使用lein run运行时则不行,除非我包含doall包装器。 (doall (repeat println 2))有效,我很好奇为什么。没有它,lein run不会在输出中显示两个空行。

我也有:

(defmacro newPrint1 [& args] `'(println ~args))
(defmacro newPrint2 [& args] `'(println ~@args))

我想到的第一个功能。接下来的两个宏是我在Udemy上关注的教程视频中的示例。即使我使用doall包装宏调用,例如(doall (newPrint1 1 2 3))lein run也不会产生输出,但终端REPL会话中的(newPrint1 1 2 3)会产生(clojure.core/println (1 2 3))的所需输出,因为它在视频教程中。为什么没有doall在这里工作?

1 个答案:

答案 0 :(得分:2)

for创建一个懒惰的序列。返回此惰性序列。 REP中的P(读取eval打印循环)打印序列,从而实现它。为了实现,运行生成每个元素的代码。

如果您不使用序列,则无法实现,因此代码永远不会运行。在非交互式使用中,情况可能就是这样。如上所述,doall迫使实现。

如果您想进行副作用,doseq通常比for更适合。