让 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 中的绑定和动态范围的主要内容,如果未能解决你的问题,请参考以下文章

将范围传递给回调函数/绑定

关于端口

范围问题中的角度绑定模型?

如何在 JSF 中正确使用组件绑定? (会话范围 bean 中的请求范围组件)

Python - 将变量范围绑定到闭包

计数和复制动态范围Vba