3

Logo 是我小时候学过的第一门编程语言。我最近发现 Logo 据说使用了动态范围,这让我很惊讶,因为我一直认为它只是使用了全局变量。这让我想知道我是否不明白动态范围的含义。

认为使用动态范围,变量会进入全局堆栈,所以当你调用另一个方法时,变量仍然是可见的。(到目前为止,就像一个全局变量。)然后,如果您声明了一个具有相同名称的新变量,它将被推入全局堆栈,隐藏原始变量。(此时,与为全局变量分配新值没有太大区别。)最后,当您退出该方法时,该新分配将从堆栈中弹出,并且该变量将恢复为其原始值。(这似乎是使其成为动态范围的关键部分,而不仅仅是重新分配全局变量。)

所以听说 Logo 使用了动态范围,我期待这个程序:

to test1
  make "x "foo
  print (se [In test1: ] :x)
  test2
  print (se [Back in test1: ] :x)
end

to test2
  print (se [In test2: ] :x)
  make "x "bar
  print (se [Still in test2: ] :x)
end

test1

有这个输出:

In test1: foo
In test2: foo
Still in test2: bar
Back in test1: foo

但是当我在 FMSLogo 中运行它时,它实际上有这样的输出:

In test1: foo
In test2: foo
Still in test2: bar
Back in test1: bar

这实际上符合我小时候的记忆,并且与我所期望的一致,如果有一个名为x. 但我不明白这是动态范围——变量永远不会超出范围!

那么为什么引用,例如这个引用,声称 Logo 使用动态范围呢?

4

1 回答 1

3

徽标确实具有动态范围,但您的示例没有局部变量,因此在test2函数中设置的变量是全局变量。您需要使用local关键字而不是make关键字来创建局部变量。

这应该演示动态范围:

to test1 :x
  test2
end

to test2
  print (se [In test2: ] :x)
end

make "x "foo    
test2
test1 "bar

如果我做对了(自从我写任何徽标以来大约有 20 年),它应该产生:

In test2: foo
In test2: bar

直接调用test2函数使用全局变量,但是从test1它调用时将使用传入的参数test1而不是全局变量。

于 2014-03-20T11:25:16.653 回答