2017-05-13 112 views
1

考虑下面的Ocaml程序编写代码:静态范围VS动态作用域

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) 

据我了解,静态范围使用代码的结构来确定变量的值,所以在这种情况下,x被替换与2都在change(x+3)。但是,我不明白为什么动态范围只能用4代替change中的x,而不是x(x+3)中用4代替。

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

回答

2

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

let change z = z - x 

功能change使用x但没有定义它。

作用域的本质是确定一个自由变量指的是什么变量定义,它指的是什么对象是。在您的示例代码中,它归结为确定change函数中自由变量x的引用。

对于静态范围,每个自由变量都有一个静态参照物。通过静态地包含代码块直到找到绑定(定义),通过在程序的文本中向外看外部来确定所指对象。在OCaml中,变量绑定是通过函数定义和let引入的。因此,您正在寻找最接近的change封闭块,其绑定xx的最近结合是let proc x =中的功能参数x。对于示例呼叫,它具有值2。

对于动态范围界定,指涉是通过嵌套函数查找确定电话是活跃在需要的值的时间。换句话说,您希望在调用链中找到定义名为x的变量的最内层函数。如果你假装OCaml有动态作用域(它最肯定),调用链是这样的:

proc => app => change 

外面change调用链功能是app,它定义一个变量名为x。因此,对于示例代码,change的自由变量x指的是由app定义的变量x。在该示例中,它的值为4

x in x + 3不是一个自由变量。它由proc定义,并用于proc。对于示例调用,无论使用哪个范围,它都有值2。

为什么它的价值我认为这不是特别有用的想法用值替换变量。最好把它们看作是绑定到价值观上的。

我也想说(虽然我可能不应该)动态范围是疯了。额外的灵活性绝对不值得额外的复杂性来弄清楚发生了什么。不应该有必要追踪函数调用链来确定变量的绑定。 (在我看来。)

+0

这是一个很好的解释!谢谢一堆! – thestateofmay