对Clojure的懒惰评估发生了什么

Joh*_*ang 4 clojure lazy-evaluation

我正在扭曲我的旧java/python头部的clojure方式.请帮助我理解clojure的懒惰特征.

=> (def myvar (lazy-seq [1 2 (prn "abc")]))
#'user/myvar
Run Code Online (Sandbox Code Playgroud)

以上内容很容易理解.由于它是一个懒惰的序列,(prn"abc")将不会被评估,因此没有打印.

=> (def myvar (lazy-seq [1 2 (prn undefined-var)]))
CompilerException java.lang.RuntimeException: Unable to resolve symbol: undefined-var in this context, compiling:(NO_SOURCE_PATH:1) 
Run Code Online (Sandbox Code Playgroud)

如您所见,上面会出现错误.为什么?

我的(错误的)理解是,因为它是懒惰的,所以(prn undefined-var)可以合法地在这里,即使"undefined-var"尚未定义.

请任何人以正确的方式指出我的理解.

Dan*_*ero 9

当clojure读者发现

 (def myvar (lazy-seq [1 2 (prn undefined-var)]))
Run Code Online (Sandbox Code Playgroud)

它需要编译它,这就是它抛出错误的原因,因为未定义undefined-var.在第一种情况下,它编译好,但是在你使用seq之前它不会被执行.


Paw*_*ski 8

以上两个答案都为您提供了有关该主题的良好信息,但我将尝试在此处确定关键问题.当您在REPL上编写s表达式时,(+ x 2)就会发生两件事情:

  1. 读者解析产生形式的字符,如符号,
  2. 评估表格.

懒惰评估推迟了第二步,但在第一步中,当读者遇到undefined-var它时,它试图将其转换为符号,并发现没有定义这样的符号.