【发布时间】:2018-11-06 09:20:20
【问题描述】:
我目前正在使用 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 在这里不起作用?
【问题讨论】:
-
请提供确切的重现步骤。 A(尽可能短,根据minimal reproducible example 指南)
project.clj,它调用的完整命名空间(与手头的行为无关的所有内容都已删除)等。 -
...事情是这样的——一般问题需要详细了解 AOT 编译,并且范围并没有真正缩小到足以回答的程度(此外,问题可能是由完全不相关的事情引起的,例如
project.clj中的错误导致执行不同的命名空间,或者返回值和副作用之间的混淆)。我们无法告诉您所有 AOT 编译到 REPL 样式内联评估的方式,但是如果您向我们展示重现器,我们可以描述导致您的问题的任何 一个 差异. -
(doall (repeat println 2))工作正常吗?如果是这样,您可能会考虑将您的问题编辑为(狭义地!)询问为什么特定的doall是必要的,而不是提出更广泛的问题。 (基本上,因为 REPL 会打印评估命令的结果,它会强制实现惰性序列——例如由map和for生成的序列)。 -
@CharlesDuffy 将其包装在
doall中适用于重复语句,但不适用于宏。我将编辑问题以反映这一点。谢谢!
标签: clojure leiningen read-eval-print-loop