Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/powerbi/2.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
Scheme 为什么要将语法分析与执行分离?_Scheme_Sicp - Fatal编程技术网

Scheme 为什么要将语法分析与执行分离?

Scheme 为什么要将语法分析与执行分离?,scheme,sicp,Scheme,Sicp,在SICP第4章中,通过将语法分析与执行分离,修改了元循环计算器,使eval过程如下所示: (define (eval exp env) ((analyze exp) env)) 这本书说,这将节省工作,因为analyze将在表达式上调用一次,而执行过程可能被调用多次 我的问题是,这种优化是如何工作的?它适用于递归过程调用,但其他情况如何?求值器一个接一个地求值表达式,eval仍将对每个表达式调用,即使它们具有相同的形式。您需要看到以下几点:(a)analyze函数只对每个表达式进行一

在SICP第4章中,通过将语法分析与执行分离,修改了元循环计算器,使
eval
过程如下所示:

(define (eval exp env)
    ((analyze exp) env))
这本书说,这将节省工作,因为
analyze
将在表达式上调用一次,而执行过程可能被调用多次


我的问题是,这种优化是如何工作的?它适用于递归过程调用,但其他情况如何?求值器一个接一个地求值表达式,
eval
仍将对每个表达式调用,即使它们具有相同的形式。

您需要看到以下几点:(a)
analyze
函数只对每个表达式进行一次遍历,(b)在扫描语法的
analyze
之外没有代码,(c)
analyze
返回的函数不会调用自身,因此运行该函数不会导致对语法的进一步扫描,(d)这与通常的求值函数不同,在求值函数中,两次调用函数意味着其语法被扫描两次


顺便说一句,
analyze
的更好名称是
compile
——它确实将输入语言(sexprs)翻译成目标语言(函数,在这里充当机器代码)。

编译器和解释器的区别在于:

编译器只扫描源代码一次,然后将其更改为执行代码(可能是机器代码)。下次执行程序时,直接执行执行代码而不分析源代码,这是非常有效的

但是,每次执行程序时,解释器都会分析源代码

此优化仅在程序将执行多次的情况下才有意义。


正如@Eli Barzilay所说,“对于
analyze
来说,更好的名称是
compile
”,您分析的函数就像执行代码一样。递归函数类似于多次执行的程序。

分析
只进行一次语法分析,并将转换后的
定义
等存储在执行相关过程时可通过
查找变量值
直接使用的环境中

相反,原始的元循环计算器扭曲了语法分析和执行,使得每次执行也调用语法分析

此链接可能有帮助:

首先感谢您的回答:)这种优化只在递归调用的情况下才有意义吗?如果我有一个过程
(define(loop)(loop))
,那么不会为每个递归调用分析
(loop)
。但是如果我有两个相同的
if
表单,那么当我们调用
eval
时,将对它们进行分析。也许我在试图理解这一点时弄错了。每当函数被多次调用时,它就会应用,节省在第二次调用时进行的扫描等。但是这些当然不是那么重要,只有递归函数的差异才有意义。但是“only”是一种轻描淡写的说法,因为递归基本上与循环相同——没有递归就等于没有循环,在这样的世界中,编译根本没有意义。