为什么将语法分析与执行分开?
在 SICP 第 4 章中,通过将语法分析与执行分离来修改元循环求值器,使 eval
过程看起来像:
(define (eval exp env)
((analyze exp) env))
书上说这将节省工作,因为 analyze
将在表达式上调用一次,而执行过程可能会被调用多次。
我的问题是,这种优化是如何进行的?它适用于递归过程调用,但其他情况又如何呢?求值器逐个求值表达式,即使它们具有相同的形式,仍会在每个表达式上调用 eval
。
In SICP Chapter 4, the metacircular evaluator is modified by separating the syntax analysis from the execution, making the eval
procedure look like:
(define (eval exp env)
((analyze exp) env))
and the book says that this will save work since analyze
will be called once on an expression, while the execution procedure may be called many times.
My question is, how does this optimization work? It will work for recursive procedure calls, but how about other cases? The evaluator evaluates expressions one after another, eval
will still be called on each expression even if they have identical forms.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您需要看到几件事:(a)
analyze
函数对每个表达式精确地遍历一次,(b)analyze
之外没有扫描语法的代码,( c)analyze
返回的函数不会调用自身,因此运行该函数永远不会导致对语法的任何进一步扫描,(d) 这与通常的评估函数不同,在通常的评估函数中,调用函数两次意味着它的语法被扫描两次。顺便说一句,
analyze
的一个更好的名字是compile
——它确实将输入语言 (sexprs) 翻译成目标语言(一个函数,在这里充当机器代码) )。You need to see several things: (a) the
analyze
function walks over each expression exactly once, (b) there is no code outside ofanalyze
that scans the syntax, (c) the function thatanalyze
returns does not call itself therefore running that function never leads to any further scanning of the syntax, (d) this is all unlike the usual evaluation functions where calling a function twice means that its syntax is scanned twice.BTW, a much better name for
analyze
iscompile
-- it really does translate the input language (sexprs) to a target one (a function, acting as the machine code here).编译器和解释器之间的区别在于:
编译器只扫描一次源代码并将其转换为执行代码(可能是机器代码)。下次执行程序时,直接执行执行代码,无需分析源代码,效率很高。
然而,解释器会在您每次执行程序时分析源代码。
这种优化仅在程序被执行多次的情况下才有意义。
正如 @Eli Barzilay 所说,“
analyze
的更好名称是compile< /code>”,你分析的函数就像执行代码。递归函数就像会执行多次的程序。
The difference between a compiler and a interpreter is that:
A compiler scan your source code only once and change it into to execution code (machine code maybe). When you execute your program the next time, you directly execute the execution code without analyzing the source code, which is efficient.
A interpreter, however, analyze the source code each time you execute your program.
This optimization only makes sense in cases of your program will be executed more than once.
As @Eli Barzilay said, "a much better name for
analyze
iscompile
", your analyzed functions is like the execution code. The recursive functions are like programs which would be executed more than once.analyze
只是进行一次语法分析,并将转换后的definition
等存储在环境中,可以直接通过lookup-variable-value
使用执行相关程序。相比之下,原始的元循环求值器扭曲了语法分析和执行,使得每次执行也调用语法分析。
此链接可能有帮助:
http://www.cs.brandeis.edu/ 〜mairson/Courses/cs21b/Handouts/feeley-notes.pdf
analyze
just does syntax analyses once and store the transformeddefinition
and so on in the environment which may be used throughlookup-variable-value
directly when the related procedure is executed.In contrast, the original metacircular evaluator twists the syntax analysis and execution which makes each execution invokes syntax analysis as well.
This link maybe helpful:
http://www.cs.brandeis.edu/~mairson/Courses/cs21b/Handouts/feeley-notes.pdf