OpenDSA 完整目录

Chapter 30 Interpreting the Functional Language SLang

| 关于   «  1. 定义 SLang 1   ::   目录   ::   3. Let 表达式  »

2. 基于环境的求值模型

2.1. 环境数据结构

在纯 \(\lambda\)-演算解释器中:

在求值函数调用时,实参(的值)实际上会被 替换 到函数体中, 取代形参(具体取决于归约策略:正则序还是应用序)。

在我们这个应用型 \(\lambda\)-演算解释器中:

我们保证替换仍然是推理函数行为的一种有效方式,但在解释器的实现 中,我们不再采用 替换模型 ,而是采用 基于环境的求值模型 , 其中值被绑定到标识符(变量名)。

从概念上讲,环境是一组(可能为空的)变量-值对。我们将把这个 集合本身以及其中的每一对都表示为一个数组。例如:

E = [ ]    // the empty environment

E = [ ["y",4], ["x",5], ["f",<sqr_fn>] ]
           // the environment in which y is bound to 4
           //                          x is bound to 5
           //                          f is bound to the squaring function

实际上,环境不止一个,因为作用域不止一个。例如,变量 “x” 可能 在一个作用域中绑定到值 5,而在另一个作用域中绑定到平方函数。

在 JavaScript 中,每个函数都定义自己的作用域。由于函数定义可以 嵌套在其他函数内部,作用域(以及环境)也可以嵌套。我们将使用 嵌套数组来表示环境的这种层次结构。例如,对于下面这段 JavaScript 代码:

function f(x,y) {
  return function (x) {
      return function (y,z) {
         // compute with x,y,z (**)
       };
    };
}
var id = function (x) { return x; };
f(1,2)("hi")(true, id);

其环境对应的嵌套数组将是:

[ "Env",                  // our usual tag

  [ ["y",true],           // the set of bindings in the innermost scope,
    ["z",id]],            // i.e., the top of the stack of environments

  [ "Env",                // the sets of bindings in all of the outer scopes,
                          // i.e.,the rest of the stack of environments
    [["x","hi"]],         //          .
                          //          .
    [ "Env",              //          .
      [["x",1],["y",2]],  //          .
      ["EmptyEnv"]]]]     //          .

环境包含变量到值的绑定。整数是一类值。但函数抽象又是怎样一类 值呢?

它是一个函数定义,包含形参列表、函数体,以及一个 闭包 (closure) ——闭包把一个匿名函数定义与当前环境(即函数定义时存在的那个环境) 打包在一起。

例如,定义匿名函数: fn (f) => (f x)
在环境: E1 = [ "Env", [ ["x", 5] ], [ "EmptyEnv" ] ] 中,
会得到如下新值: [ "Clo", [ "f" ], (f x), E1 ]
也就是说,这个匿名函数唯一的参数是函数 f ,函数体是对 f 以实参 x 的调用,其环境为 E1 。
如果这个闭包后来被绑定到变量 g ,如下所示: (fn (g) => (g 1) fn (f) => (f x))
那么在把 g 应用于 1 的那个位置上,环境是: E2 = [ "Env", [ ["g", [ "Clo", [ "f" ], (f x), E1 ] ] ], E1 ]

在编程语言中, 指称值 (denoted value)是任何可以绑定到变量名 的值。因此, 环境 不过是从标识符(例如 “x” 和 “g”)到指称值 的映射。

指称值的类型因编程语言而异。在 SLang 1 中,指称值只有两种类型: 数值和闭包。

像往常一样,我们用数组来表示这些指称值,其第一个元素分别是标签 “Num” 或 “Clo”。

这意味着,如果我们严格遵循上面 E1 中环境的表示方式,就应该 把 5 到 “x” 的绑定写成:

[ "x", [ "Num", 5 ] ]

而不是

[ "x", 5 ]

2.2. 确定变量所绑定的值

下面的问题让你练习确定 SLang 1 中某个变量绑定到哪个值。要获得 这道题的学分,你必须连续三次正确完成这个随机化问题。

2.3. 在环境中对表达式求值

下面的问题让你练习对 SLang 1 表达式进行完整求值。要获得这道题 的学分,你必须连续三次正确完成这个随机化问题。

2.4. 确定 SLang 1 中的指称值

下面的问题让你练习 SLang 1 解释器中的指称值。要获得这道题的学分, 你必须连续三次正确完成这个随机化问题。

   «  1. 定义 SLang 1   ::   目录   ::   3. Let 表达式  »

关闭窗口