Functional programming 让绑定和动态范围在SML中

Functional programming 让绑定和动态范围在SML中,functional-programming,scope,closures,sml,Functional Programming,Scope,Closures,Sml,我正在参加Coursera上的编程语言课程,我很难理解以下关于静态和动态范围的示例 考虑代码示例和与之相关的测验 fun f g = let val x = 9 in g() end val x = 7 fun h() = x+1 val y = f h y在词法范围(如在ML中)和下有什么值 动态范围(与ML不同) 这个问题的答案是“8在词法范围下,10在动态范围下”,给出的理由是“在动态范围下,函数h的主体最终会“看到”x到9的局部绑定,如果我们删除这个局部绑定(因为它似乎没有任何用途),

我正在参加Coursera上的编程语言课程,我很难理解以下关于静态和动态范围的示例

考虑代码示例和与之相关的测验

fun f g = let val x = 9 in g() end
val x = 7
fun h() = x+1
val y = f h
y在词法范围(如在ML中)和下有什么值 动态范围(与ML不同)

这个问题的答案是“8在词法范围下,10在动态范围下”,给出的理由是“在动态范围下,函数h的主体最终会“看到”x到9的局部绑定,如果我们删除这个局部绑定(因为它似乎没有任何用途),那么动态范围将导致一个未定义的变量。”

考虑下面的代码片段和关于为什么动态范围在这种情况下不起作用的解释

fun f y =
 let val q = y+1 
 in fn z => q + y + z
 end
val g = f 4
val y = 5
val z = g 6
在动态范围下,现在对G6的调用将毫无意义:我们将尝试查找q,但在调用站点的环境中没有q


在第一个示例中,考虑了let表达式“val x=9”中的局部val绑定,而在第二个示例中,不考虑“val q=y+1”。这背后的原因是什么?

在第一个示例中,调用
g()
val x=9
在范围内,因此
g
可以在动态范围规则下查看它


在第二个示例中,
val q=y+1
仅在
f
的范围内。在第一个示例中,当在
valz=g6

行调用
g
时,它不在范围内,“如果我们删除x到9的局部绑定,那么动态范围将导致未定义的变量”。既然存在另一个x到7的全局绑定,是否可以使用它来代替引发未定义变量异常?@srib您是对的,如果您删除了本地x,它应该使用全局x,而不是导致未定义变量错误。这似乎是文本中的错误。感谢您的澄清。那么,我可以假设在动态作用域中,如果返回其他函数的高阶函数具有局部变量(假设程序没有与局部变量同名的全局变量),程序将无法编译?@srib通常在运行时检查动态作用域,而不是在编译时检查,因此程序不会编译失败,但在运行时会出现异常。在一种动态范围但静态类型的语言中,是的,如果您从函数返回
fn x=>x+y
,然后在未定义
y
的地方调用它,程序将不会编译(注意,它不必是全局的-您可以在调用位置使用局部变量)返回
fn x=>x+y
的函数是否定义了名为
y
的变量没有区别。换句话说,在动态作用域语言中没有词汇闭包。这听起来不像动态作用域,因为它通常起作用。@molbdnilo,你是指第一个例子吗?