动态作用域 - 深绑定 vs 浅绑定

30

我一直在尝试理解浅绑定和深绑定,但维基百科没有很好地解释清楚。如果我有以下代码,在使用动态作用域的语言中:

a) 使用深度绑定,输出是什么?

b) 使用浅绑定,输出是什么?

x: integer := 1
y: integer := 2

procedure add
  x := x + y

procedure second(P:procedure)
  x:integer := 2
  P()

procedure first
  y:integer := 3
  second(add)

----main starts here---
first()
write_integer(x)

这是Python吗?你的问题是否与语言无关?请具体说明。 - Shimmy Weitzhandler
3个回答

30

Deep binding(深度绑定)在将过程作为参数传递时,会绑定当时的环境。

Shallow binding(浅度绑定)在实际调用过程时,会绑定当前的环境。

因此,在使用深度绑定的动态作用域中,当add被传递到第二个过程时,环境是x = 1,y = 3,而x是全局x,所以它将4写入全局x中,这是write_integer捕获到的x。

浅度绑定只会遍历到最近与名称对应的变量,因此答案将是1。


2
对于浅绑定,如果我在 second 过程中(在 P() 之前)放置 "write_integer(y)",我会得到 3 还是 2?此外,对于浅绑定,我是否无法更改全局变量的值? - vvMINOvv
1
动态作用域与浅绑定将打印“5”。这是因为动态作用域使用从调用它的方法中获取的绑定(变量值组合)。因此,具有浅绑定的动态作用域将使用绑定x = 2,而不是具有深绑定的动态作用域,后者将使用(如@jjia6395所说)x = 1(即将add作为参数传递到second方法时的绑定)。 - Antoine Dahan
@AntoineDahan 如果 second 动态引入了新的绑定来命名一个新变量,该变量恰好被命名为 x(如其使用 x:integer := 2 而不是 x := 2 所示),那么 add(在 second 存活时从 second 调用)会将动态创建的 x 更改为 5。但是 write_integer(x) 引用了全局的 x。因此,这个伪代码是误导性的。它应该在定义中使用 "=",如 x:integer = 1,并在变异赋值中使用 ":=",如 x := x + y - Will Ness
话虽如此,我反对这种术语的误用——在LISP上下文中,它们首次出现时,“深”和“浅”只是动态或词法作用域的实现技术,并且可以用于实现两者,因此如果正确实现,则在程序内部无法区分。这里所谓的“深度”绑定只是一种误解——它应该改为讨论“自由变量解析时间”,并通过编写second(closed(add,(x,y)))来使其明确。在两种情况下,它仍然是动态名称解析。你只是想要冻结它们。所以冻结它们。明确地! - Will Ness

0

a) 在深度绑定中,我们处理 add 的环境,在这个环境中,x 指的是全局 x,y 指的是第一个函数(最后执行的声明 y 的函数)本地的 y。

x(全局)=x(全局)+y(本地):x=1+3=4

b) 在浅绑定中,我们处理 second 的环境,在这个环境中,x 指的是 second 本地的 x,y 指的是第一个函数(最后执行的声明 y 的函数)本地的 y。

x(本地)=x(本地)+y(本地):x=2+3=5

但是:write_integer(x)输出的是等于 1 的全局 x。

最后:

a)4

b)1


-3

9
不,使用浅层绑定会输出 1,正如 jjia6395 所说的那样。这是因为对 P() 的调用修改了 second 局部作用域中的 x,当 second 返回时,该变量也随之消失。而对 write_integer(x) 的调用打印的是未被修改的全局变量 x - ruakh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接