【发布时间】:2010-12-11 11:26:05
【问题描述】:
我正在为 Scheme 编写一个小型评估器。
我需要用替换模型编写评估器,因此不能使用像set! 这样的赋值。
但是由于我仍然需要在某个地方存储原始过程和 user-defined 变量,我需要一个环境吗?如果是,替代模型和环境模型有什么区别?
谢谢。
【问题讨论】:
标签: functional-programming scheme
我正在为 Scheme 编写一个小型评估器。
我需要用替换模型编写评估器,因此不能使用像set! 这样的赋值。
但是由于我仍然需要在某个地方存储原始过程和 user-defined 变量,我需要一个环境吗?如果是,替代模型和环境模型有什么区别?
谢谢。
【问题讨论】:
标签: functional-programming scheme
不——对于一个普通的基于替换的评估器,你确实不需要需要一个环境。这是因为一旦你有了一个绑定(例如,当你执行一个函数调用时),你立即用值替换名称,所以没有必要保留名称->值映射。事实上,您可以将环境视为一种避免替换所涉及的开销的方法,方法是缓存它们并在以后执行它们。请参阅PLAI 了解遵循此观点的教科书——事实上,它从替换到替换缓存,直到后来才将术语更改为环境。
但请注意,使用set! 的问题与所有这些无关。当您考虑set! 时,您首先需要明确您所谈论的set! 的级别:如果它是您实现的语言而不是实现本身,那么可以在给定任何类型的可变值的情况下添加它——例如,在Racket 中,您可以使用boxes,这足以在语言中实现set!。这通常在基于环境的评估器中完成,其中环境类型从映射名称到值更改为将名称映射到 locations(实现为框或类似的可变值)。但这并不是真正必要的:您仍然可以使用基于替换的评估器来做到这一点,其中这些框正在成为您要替换的值域的一部分。举一个具体的例子,你可以从一个表达式开始(使用类似方案的语言):
(let ((x 1))
(begin (set! x 2)
(set! x 3)))
而不是将1 替换为x,您将分配一个包含1 的框,然后替换那个相同的框,从而得到
(begin (set! #<box> 2)
(set! #<box> 3))
两个#<box>es 是那个盒子。 (请注意,这不是我正在谈论的实现代码,而是您正在评估的语言中的表达式。)通常不这样做的原因是它可能会造成混淆——您需要将值表示为框可以替换,这些框不是源用户程序的一部分,但它们是解释器应该处理的值(例如,最后一个 #<box> 是返回值——但它是你想要的值返回,而不是盒子),并且您需要注意盒子的身份(例如,上面的两个盒子必须是相同的盒子,以便解释第一个set!在第二个中可见)。
因此,如果您只是学习编写口译员,不建议这样做。如果是这样的话,那我建议你看看那本教科书。
【讨论】:
是的,您仍然需要一个环境,因为正如您所说,您需要能够存储变量等。
替代模型是一种帮助您了解如何评估给定过程的方法。比如可以定义平方函数
(define (square x) (* x x))
使用替换模型,如果你调用了
(square 4)
然后将 4 替换为函数定义中每次出现的 x
(* 4 4) => 16
环境用于可视化变量和状态在解释器中的存储方式。所以简而言之,替换模型用于帮助您评估过程,而环境用于查看您的解释器将如何记住用户在使用您的解释器时可能定义的变量和定义。
【讨论】: