Clojure 和 Leiningen:为什么在此示例中需要“doall”?

Clojure and Leiningen: Why is `doall` needed in this example?

我目前正在使用 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 在这里不起作用?

for 创建惰性序列。返回此惰性序列。 REPL中的P(read eval Print loop)打印序列,从而实现。为了实现,产生每个元素的代码是运行.

如果不使用sequence是没有实现的,所以代码永远不会运行。在非交互式使用中,很可能就是这种情况。如前所述,doall 强制实现。

如果你想做副作用,doseq 通常比 for 更适合。