gpt4 book ai didi

scope - 静态(词法)作用域与动态作用域(伪代码)

转载 作者:行者123 更新时间:2023-12-02 23:27:56 26 4
gpt4 key购买 nike

Program A()
{
x, y, z: integer;

procedure B()
{
y: integer;
y=0;
x=z+1;
z=y+2;
}

procedure C()
{
z: integer;

procedure D()
{
x: integer;
x = z + 1;
y = x + 1;
call B();
}

z = 5;
call D();
}

x = 10;
y = 11;
z = 12;
call C();
print x, y, z;
}

据我了解,使用静态作用域运行该程序的结果是:x=13、y=7 和 z=2。

但是,当使用动态作用域运行时,结果为:x=10、y=7 和 z=12。

这些结果是我们的教授给我们的结果。然而,我一生都无法理解他是如何取得这些成果的。有人可以解释一下伪代码并在两种不同类型的范围中解释它们的值吗?

最佳答案

通过静态(词法)作用域,程序源代码的结构决定了您引用的变量。通过动态作用域,程序堆栈的运行时状态决定了您引用的变量。这可能是一个非常陌生的概念,因为基本上当今广泛使用的每种编程语言(emacs lisp 除外)都使用词法作用域,这对于人类和分析工具来说都更容易推理。

考虑这个更简单的示例程序(用伪代码语法编写):

program a() {
x: integer; // "x1" in discussions below
x = 1;

procedure b() {
x = 2; // <-- which "x" do we write to?
}

procedure c() {
x: integer; // "x2" in discussions below
b();
}

c();
print x;
}

程序和编译器将这两个变量引用为 x ,但我已将它们标记为 x1x2以方便下面的讨论。

通过词法作用域,我们在编译时确定哪个 x我们指的是基于静态、词法结构的程序源代码。 x的最里面的定义在定义 b 时的范围内是 x1 ,因此有问题的写入解析为 x1 ,这就是x = 2的地方写,所以我们打印 2运行该程序后。

通过动态作用域,我们可以在运行时跟踪一堆变量定义 - 因此 x我们写入的内容取决于范围内的内容以及在运行时动态定义的内容。开始运行ax => x1入栈,调用 cx => x2到堆栈上,然后当我们到达 b 时,栈顶是x => x2 ,所以我们写入 x2 。这留下x1保持不变,因此我们打印 1在程序结束时。

此外,考虑这个稍微不同的程序:

program a() {
x: integer; // "x1" in discussions below
x = 1;

procedure b() {
x = 2; // <-- which "x" do we write to?
}

procedure c() {
x: integer; // "x2" in discussions below
b();
}

c();
b();
}

注意b被调用两次——第一次是通过 c ,直接第二次。使用词法作用域,上面的解释不会改变,我们写入 x1两次。然而,对于动态作用域,这取决于如何x在运行时绑定(bind)。我们第一次调用b ,我们写入x2如上所述 - 但第二次,我们写入 x1 ,因为那是堆栈顶部的内容! (当 x => x2 返回时 c 被弹出。)

所以,这是您教授的代码,注释了哪个确切变量用于哪个具有词法作用域的写入。最终在程序末尾打印的写入标记有 * :

program A()
{
x, y, z: integer; // x1, y1, z1

procedure B()
{
y: integer; // y2
y=0; // y2 = 0
x=z+1; // x1 = z1 + 1 = 12 + 1 = 13*
z=y+2; // z1 = y2 + 2 = 0 + 2 = 2*
}

procedure C()
{
z: integer; // z2

procedure D()
{
x: integer; // x2
x = z + 1; // x2 = z2 + 1 = 5 + 1 = 6
y = x + 1; // y1 = x2 + 1 = 6 + 1 = 7*
call B();
}

z = 5; // z2 = 5
call D();
}

x = 10; // x1 = 10
y = 11; // y1 = 11
z = 12; // z1 = 12
call C();
print x, y, z; // x1, y1, z1
}

这里是动态作用域。请注意,更改位于 B 中。 ,并在 * 的位置标签:

program A()
{
x, y, z: integer; // x1, y1, z1

procedure B()
{
y: integer; // y2
y=0; // y2 = 0
x=z+1; // x2 = z2 + 1 = 5 + 1 = 6
z=y+2; // z2 = y2 + 2 = 0 + 2 = 2
}

procedure C()
{
z: integer; // z2

procedure D()
{
x: integer; // x2
x = z + 1; // x2 = z2 + 1 = 5 + 1 = 6
y = x + 1; // y1 = x2 + 1 = 6 + 1 = 7*
call B();
}

z = 5; // z2 = 5
call D();
}

x = 10; // x1 = 10*
y = 11; // y1 = 11
z = 12; // z1 = 12*
call C();
print x, y, z;
}

关于scope - 静态(词法)作用域与动态作用域(伪代码),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22394089/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com