静态范围与动态范围

时间:2017-05-13 00:17:10

标签: scope ocaml

考虑以下Ocaml代码:

let app f y = let x = 4 in (f y)+1 ;;
let proc x = let change z = z-x in app change (x+3) ;; 
(proc 2)

根据我的理解,静态作用域使用代码的结构来确定变量的值,因此在这种情况下,x2都替换为change(x+3)x。但是,我不明白的是,为什么动态作用域仅用change取代4中的x而取代(x+3) 4取代DATEADD() {1}}。

这有点令人困惑,我想知道如何解决这些问题是否有任何诀窍。

1 个答案:

答案 0 :(得分:2)

自由变量是在函数中使用但未在函数中定义的变量。在您的示例代码中,唯一的自由变量是函数x的变量change

let change z = z - x

函数change使用x但未定义它。

范围界定的本质是确定自由变量引用的变量定义, referent 是什么。在您的示例代码中,它归结为确定x函数中自由变量change的引用。

对于静态作用域,每个自由变量都有一个静态指示对象。通过静态地包含代码块向外查看程序文本来确定引用,直到找到绑定(定义)。在OCaml中,变量绑定由函数定义和let引入。因此,您正在寻找绑定change的{​​{1}}最近的封闭区块。最近的x绑定是x中的函数参数x。对于示例调用,它的值为2.

对于动态范围,通过查找在需要值时处于活动状态的嵌套函数调用来确定引用对象。换句话说,您希望在调用链中找到定义名为let proc x =的变量的最内层函数。如果你假装OCaml有动态范围(它绝对),那么调用链看起来像这样:

x

调用链中proc => app => change 之外的函数是change,它定义了一个名为app的变量。因此,对于示例代码,x的自由变量x是指由change定义的变量x。在示例中,它具有值app

4中的x不是自由变量。它由x + 3定义,并在proc中使用。对于示例调用,无论使用何种范围,它都具有值2.

对于它的价值,我认为考虑用值替换变量并不是特别有用。最好将它们视为与价值观相关联。

我还想说(虽然我可能不应该)动态范围是疯狂的。在确定正在发生的事情时,额外的灵活性绝对不值得额外的复杂性。不必跟踪函数调用链以确定变量的绑定。 (在我看来。)