Clojure (println(iterate inc 0)):为什么会开始打印?
当我在repl中运行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
(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
,原因与此相同。