Lisp 关于SICP chpt 4.1的问题:分析expr如何帮助加快评估?
我正在阅读SICP的以下部分 根据本文,以下对Lisp 关于SICP chpt 4.1的问题:分析expr如何帮助加快评估?,lisp,scheme,sicp,Lisp,Scheme,Sicp,我正在阅读SICP的以下部分 根据本文,以下对eval的转换将提高性能,因为一个表达式经过多次求值,只能分析一次 (define (eval exp env) ((analyze exp) env)) 这是本书中给出的分析函数: (define (analyze-if exp) (let ((pproc (analyze (if-predicate exp))) (cproc (analyze (if-consequent exp))) (aproc (ana
eval
的转换将提高性能,因为一个表达式经过多次求值,只能分析一次
(define (eval exp env)
((analyze exp) env))
这是本书中给出的分析
函数:
(define (analyze-if exp)
(let ((pproc (analyze (if-predicate exp)))
(cproc (analyze (if-consequent exp)))
(aproc (analyze (if-alternative exp))))
(lambda (env)
(if (true? (pproc env))
(cproc env)
(aproc env)))))
我不明白为什么书上说analyze
只运行一次。eval
的主体,即((analyze exp)env))
是否基本上说,每次调用eval
时,analyze
都将以exp
作为参数进行调用?这意味着每次调用eval
时都会调用analyze
我的理解有什么问题?如果有任何反馈,我将不胜感激,谢谢 实际上,每次使用程序代码作为参数调用
eval
,都会调用语法计算器。但是,当该代码中的一个函数调用该代码中的另一个函数(或者,在最简单的情况下,它通过递归调用自己)时,内部的apply
将得到分析的表达式(最终是lambda函数)作为参数,而不是一堆需要再次进行语法分析才能执行的代码。Gintautas的答案是正确的,但也许有一个例子是正确的。假设您已经开发了一个使用循环构造的Scheme方言
(do-n-times n expr)
具有明显的语义。现在,当您调用naiveeval
来计算一个运行十次的循环时
(eval '(do-n-times 10 (print 'hello)))
然后,它将对环体进行十次分析。使用将分析与评估分离的eval
版本,循环体是analyze
d一次,然后评估十次
分析阶段返回一个过程,该过程在Scheme解释器中可能很快,也可能不快。然而,它可以进行各种优化(死代码分析、机器代码等)。拉斯曼的答案非常好 作为补充答案,还可以将
analyze(environ)
视为eval(expr,environ)
的一种格式,其中参数expr
已提前传递。在SICP中,您可以阅读如下示例代码:
(define (analyze-assignment exp)
(let ((var (assignment-variable exp))
(vproc (analyze (assignment-value exp))))
(lambda (env)
(set-variable-value! var (vproc env) env)
'ok)))
当您看到一个let(([var][preprocessed stuff])
时,它将预处理存储在一个闭包中,直到稍后传入environ
时需要它