让 SML 中的绑定和动态范围
Posted
技术标签:
【中文标题】让 SML 中的绑定和动态范围【英文标题】:Let bindings and dynamic scope in SML 【发布时间】:2021-06-27 18:03:40 【问题描述】:我正在 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 的本地绑定,如果我们删除了这个本地绑定(因为它似乎没有任何用途),那么动态范围将导致一个未定义的变量。"
请考虑以下代码 sn-p 以及为什么动态范围不适用于这种情况的解释。
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
在动态范围内,现在对 g 6 的调用将毫无意义:我们将尝试查找 q,但在调用站点的环境中没有 q。
在第一个示例中,考虑了 let 表达式“val x = 9”中的本地 val 绑定,而在第二个示例中,没有考虑“val q = y+1”。这背后的原因是什么?
【问题讨论】:
这听起来不像动态范围,因为它通常有效。 @molbdnilo ,你指的是第一个例子吗? 【参考方案1】:在第一个示例中,val x = 9
在调用 g()
时在范围内,因此 g
可以在动态范围规则下看到它。
在第二个示例中,val q = y+1
仅在 f
内的范围内。在val z = g 6
行上调用g
时,它不在范围内。
【讨论】:
在第一个例子中,'如果我们删除 x 到 9 的本地绑定,那么动态范围将导致一个未定义的变量'。既然有另一个全局绑定 x 到 7,那不就用它来代替抛出未定义的变量异常吗? @srib 你是对的,如果你删除了局部 x,它应该使用全局 x,不会导致未定义变量错误。这似乎是文本中的错误。 感谢您的澄清。那么我可以假设在动态作用域中,如果返回其他函数的高阶函数具有局部变量(假设程序没有与局部变量同名的全局变量),程序将无法编译? @srib 通常在运行时检查动态范围,而不是在编译时检查,因此程序不会编译失败,但会在运行时失败并出现异常。在动态范围但静态类型的语言中,是的,如果您从函数返回fn x => x+y
然后在未定义 y
的地方调用它(注意,它不必是全局的 - 你可以在调用站点有一个局部变量)并且返回fn x => x+y
的函数是否定义了一个名为y
的变量没有区别。
换句话说:动态范围的语言中没有词法闭包。以上是关于让 SML 中的绑定和动态范围的主要内容,如果未能解决你的问题,请参考以下文章