Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Clojure的惰性评估发生了什么_Clojure_Lazy Evaluation - Fatal编程技术网

Clojure的惰性评估发生了什么

Clojure的惰性评估发生了什么,clojure,lazy-evaluation,Clojure,Lazy Evaluation,我正在用clojure的方式扭曲我的旧java/python头。请帮助我理解clojure的懒惰特性 => (def myvar (lazy-seq [1 2 (prn "abc")])) #'user/myvar 以上内容很容易理解。由于它是一个延迟序列,prn abc将不会被计算,因此不会打印任何内容 => (def myvar (lazy-seq [1 2 (prn undefined-var)])) CompilerException java.lang.RuntimeEx

我正在用clojure的方式扭曲我的旧java/python头。请帮助我理解clojure的懒惰特性

=> (def myvar (lazy-seq [1 2 (prn "abc")]))
#'user/myvar
以上内容很容易理解。由于它是一个延迟序列,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) 
如您所见,上述操作将引发一个错误。为什么?

我的错误理解是,因为它是懒惰的,prn未定义的var可以合法存在,即使未定义的var尚未定义


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

您似乎有正确的理解,只是lazy seq函数不是这样工作的 下面是一个典型的例子:

user> (lazy-seq (cons 4 (range 5)))
(4 0 1 2 3 4)
lazy seq几乎总是在第一个参数 是序列中的第一项,第二个参数是代码 生成列表的其余部分。人们很少使用lazy seq 直接在日常Clojure中使用map reduce、filter、, 等等更为常见

函数中用于生成序列其余部分的代码也需要 为了能够被编译,在您的情况下,您还可以延迟编译 通过使用eval,尽管我建议不要对这样的事情使用eval 在代码中,其他人需要阅读;但这有助于伟大的学习-

user> (def myvar (lazy-seq (cons 1 (eval '(prn undefined-var))))) ; don't do this at work
#'user/myvar
user> myvar
; Evaluation aborted.
user> 

当clojure阅读器发现

 (def myvar (lazy-seq [1 2 (prn undefined-var)]))

它需要编译它,这就是它抛出错误的原因,因为未定义的var没有定义。在第一种情况下,它编译为ok,但在使用seq之前不会执行

以上两个答案都为您提供了关于该主题的良好信息,但我将在这里尝试确定关键问题。当您在REPL like+x2上写入时,会发生两件事:

通过对产生形式的字符(如符号)的分析, 表格的一部分。
第二步是延迟求值,但在第一步中,当读卡器遇到未定义的var时,它会尝试将其转换为一个符号,并发现该符号未定义。

Clojure中就是这种情况,因为Clojure脚本在执行之前必须编译为java?在其他Lisp方言中,在惰性计算上下文中使用未定义的var可以吗?嗨,John,对不起,我没有其他Lisp的经验。谢谢dAni,你的答案帮助很大。但我只能将其中一个设置为已接受。Pawel更适合我的大脑谢谢你Pawel。它变得更清晰了。源代码需要在读者阶段解析为表单。该错误仅显示解析过程失败。听起来这和懒惰的评估无关。而且它必须是所有lisp方言的常用方法。没错。据我所知,读者几乎是任何列表方言的必选部分。