当我在我的repl中运行(println (iterate inc 0))
时,我会得到这样的结果:
user=> (println (iterate inc 0))
(0 1 2 3 4 5 6 7 8 9 10 11 12 13 ....................
我运行代码时的期望是repl没有显示任何内容而只是因为(iterate inc 0)
永远不会结束而卡住了。但是,我看到(0 1 2 3 ...
。
(iterate inc 0)
生成永不返回的无限序列。如果它永远不会结束,那么为什么println
开始打印值?
换句话说,即使输入从未完成评估,为什么(println xx)
开始被评估?
答案 0 :(得分:8)
你应该在Clojure上阅读lazy seqs。他们能够产生在实现整个序列之前可以逐步消耗的值(在这种情况下,永远不会发生)。
将其视为推拉与拉动可能会有所帮助。而不是迭代创建一个完整的值列表然后将它们推送到println函数(这将永远不会发生),迭代只是将它交给一个懒惰的序列,println根据需要拉取值。这就是为什么(取5(iterate inc 0))有效;在停止之前,只尝试拉出5个值。
答案 1 :(得分:2)
Clojure的打印比System.out.println
更聪明;它可以是customized for different types。在序列的情况下,walks through element-by-element, printing each one as it goes - 我们不必等到评估整个序列才开始打印。
相比之下,在打印前调用System.out.println
的{{1}}的行为更像您的预期。它永远挂起,不打印任何东西,因为toString
需要评估整个序列 - 或者,至少,如果它没有尝试构建字符串的内存不足,它将永远挂起。
那就是说,整个表达确实被卡住了 - 如果你等着它停止打印,你就永远等待:
toString