默认局部变量

lua-users home
wiki

关于 Lua 的作用域规则的疑问会定期出现在邮件列表中。这里需要对它的设计进行说明。

Lua 的声明被描述为“默认全局”,与“默认局部”(Python 和 Ruby)形成对比。另一种选择是,没有什么是“默认的”(即需要显式声明局部变量和全局变量)。以下是一些关于此问题的见解:

[4] “默认局部变量是错误的。也许默认全局变量也是错误的,[但是]解决方案不是默认局部变量。”(Roberto)

[5] “我不太理解为什么有人会想要变量默认是*任何*东西,就像自动声明一样。它只是偶尔为你节省了一些按键,同时为寻找愚蠢的、难以找到的打字错误和名称混淆错误打开了无限的乐趣。(赋值而不是声明,反之亦然。)”(David Olofson)

[6] “问题是,如果没有 [显式] 局部变量声明,你就无法确定变量在哪个地方是局部的。” (RiciLake)

[7] “'默认局部变量' 与词法作用域不兼容。...适当的词法作用域确实要求你可以在修改绑定(赋值)和创建新绑定(声明)之间进行选择。唉,'默认局部变量' 规则将它们混合在一起,并使赋值同时执行这两项操作。” (MikePall)

[8] “在我看来,默认局部变量的主要论点是防止意外使用全局环境,其次是使声明局部变量成为可选的,从而减少输入量。就我个人而言,我认为使声明成为可选的,无论是对于局部变量还是全局变量,都是一个坏主意。为了强制对全局变量进行显式声明,以及为了防止意外使用全局环境,我使用 require 'strict'。也许可以在编译时做一些等效的(或更好的)事情。但我的观点是,也许应该问问自己,是否真的想要/需要默认局部变量,或者只是显式全局变量声明。”(Mark Meijer)

[Python PEP 3104] -- Python 对“默认局部变量”的修复,与 ReubenThomas 的提案(见下文)完全相同(除了关键字的选择!)。

[1] “ [当前的局部变量作用域规则] 是 Ruby 中最大的设计缺陷。”(松本行弘,Ruby 设计师)(评论:[9][10][7]

[2] -- 讨论各种作用域规则以及为什么 Converge 语言选择“默认局部变量”以及“非局部变量”(如 PEP 3104)关键字。(Laurence Tratt,Converge 设计师)

[3] “我不喜欢隐式声明词法变量,因为它往往会破坏它们的主要用途,即捕获拼写错误……声明应该看起来像声明……我认为使用 my 的声明是正确地霍夫曼编码的。”(Larry Wall,Perl 设计师)

另请参阅


先前提案

以下是另一个“默认局部变量”提案。我认为它更简单,更不显眼,但比其他提案提供了更好的结果。(-- ReubenThomas

更改如下

1. 添加一个新的关键字“outer”,它与“local”类似,但它声明给定名称引用封闭函数中同名的最内层变量,如果没有,则引用同名的全局变量(即使当前不存在)。

2. 函数中对变量的第一次赋值隐式地充当“local”声明,除非该变量已在该函数中显式或隐式地声明。函数外部的赋值与目前一样,对表元素的赋值也是如此。

注意

a. 保留了进行配置文件样式全局赋值的能力,但代价是使函数内部的赋值与外部的赋值方式不同。在实践中,这应该不是问题,因为很少有 Lua 脚本在顶层包含复杂的代码。如果您需要在顶层代码中使用局部变量,您只需像现在一样声明它们即可。

b. 语法上唯一的变化是添加了 "outer"(类似于其他使用 "nonlocal"、"extern" 或 "static" 关键字来声明这些不在词法作用域或任何闭包中定义的符号的用法)。

c. 语义上唯一的变化是函数内部赋值的含义。

d. 赋值只在它们出现的地方使变量局部化,而不是针对整个函数。这符合最小惊讶原则:您不必阅读整个函数才能找出给定变量是否为局部变量(编译器也不需要,因此实现很简单)。


最近更改 · 偏好设置
编辑 · 历史记录
最后编辑于 2020 年 6 月 2 日下午 3:14 GMT (差异)