Clojure (println(iterate inc 0)):为什么会开始打印?

Clojure (println(iterate inc 0)):为什么会开始打印?,clojure,lazy-sequences,Clojure,Lazy Sequences,当我在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)永远不会结束而卡住。但是,我看到了(01 2 3…) (iterate inc 0)生成永不返回的无限序列。如果它永不结束,那么为什么p

当我在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)
永远不会结束而卡住。但是,我看到了
(01 2 3…

(iterate inc 0)
生成永不返回的无限序列。如果它永不结束,那么为什么
println
开始打印值

换句话说,为什么即使输入从未完成评估,也要开始评估
(println xx)

您应该在Clojure中阅读。它们能够生成可以在实现整个序列之前增量使用的值(在本例中,这种情况永远不会发生)


将其视为push vs pull可能会有所帮助。与其迭代创建一个完整的值列表,然后将它们推送到println函数(这是永远不会发生的),iterate只是将一个延迟序列交给它,println根据需要提取值。这就是为什么(取5(iterate inc 0))有效;take在停止之前只尝试提取5个值。

Clojure的打印比
System.out.println
更智能;它可以。对于序列,它-我们不必等到整个序列被评估后才开始打印

相比之下,
System.out.println
,它在打印之前调用
toString
,其行为更像您所期望的。它永远挂起,不打印任何内容,因为
toString
需要评估整个序列-或者,至少,如果它在尝试构建字符串时没有耗尽内存,它将永远挂起

这就是说,整个表达式确实被卡住了-如果你在等待它停止打印,你会永远等待:

(do
  (println (iterate inc 0))
  (println "Never reached!"))

println
不需要在打印之前实现整个序列,它是按需执行的。“它永远不会返回”。
(首先(迭代inc 0))
将返回您
0
,原因与此相同。