Lua运算符,为什么不定义+ =, - =等等?

qri*_*kko 40 lua language-design assignment-operator compound-assignment

这个问题我有一段时间以来一直有点恼火,而且从来没有到处寻找答案.

但是我想我至少可以问这个问题,也许有人可以解释一下.

基本上我使用的许多语言都使用语法糖来编写(使用C++中的语法):

int main() {
    int a = 2;
    a += 3; // a=a+3
}
Run Code Online (Sandbox Code Playgroud)

虽然在lua +=中没有定义,所以我必须写a=a+3,这也是关于语法糖.当使用更"有意义"的变量名称时,例如:bleed_damage_over_time或者它开始变得乏味的东西:

bleed_damage_over_time = bleed_damage_over_time + added_bleed_damage_over_time 
Run Code Online (Sandbox Code Playgroud)

代替:

bleed_damage_over_time += added_bleed_damage_over_time
Run Code Online (Sandbox Code Playgroud)

所以如果你没有一个好的解决方案,我想知道如何解决这个问题,在这种情况下,我当然会有兴趣听到它; 但是为什么lua没有实现这种语法糖.

mun*_*ent 50

这只是我的猜测,但是:

1.在单通道编译器中实现它很难

Lua的字节码编译器实现为单通递归下降解析器,可立即生成代码.它不会解析为单独的AST结构,然后在第二次传递中将其转换为字节码.

这迫使对语法和语义进行一些限制.特别是,任何需要任意前瞻或前向引用的东西在这个模型中都很难支持.这意味着分配已经难以解析.给出如下内容:

foo.bar.baz = "value"
Run Code Online (Sandbox Code Playgroud)

在解析时foo.bar.baz,你没有意识到你实际上正在解析一个赋值,直到你=已经解析并生成了代码.由于这个原因,Lua的编译器在处理赋值时具有很大的复杂性.

支持自我分配将使这更加困难.就像是:

foo.bar.baz += "value"
Run Code Online (Sandbox Code Playgroud)

需要翻译成:

foo.bar.baz = foo.bar.baz + "value"
Run Code Online (Sandbox Code Playgroud)

但是在编译器遇到的时候=,它已经被遗忘了foo.bar.baz.这是可能的,但并不容易.

它可能与语法不一致

Lua实际上在语法中没有任何语句或行分隔符.空格被忽略,没有强制分号.你可以做:

io.write("one")
io.write("two")
Run Code Online (Sandbox Code Playgroud)

要么:

io.write("one") io.write("two")
Run Code Online (Sandbox Code Playgroud)

Lua对两者同样满意.保持这样明确的语法是很棘手的.我不确定,但自我指派运营商可能会变得更难.

3.多次分配不能很好

Lua支持多项任务,例如:

a, b, c = someFnThatReturnsThreeValues()
Run Code Online (Sandbox Code Playgroud)

我甚至不清楚如果你试图这样做意味着什么:

a, b, c += someFnThatReturnsThreeValues()
Run Code Online (Sandbox Code Playgroud)

你可以将自我赋值运算符限制为单一赋值,但是你刚刚添加了一个人们必须知道的奇怪角落案例.

综上所述,自我赋值运算符非常有用,值得处理上述问题.

  • 感谢一大堆花时间回答.你真的指出了我的问题中一些看似合理且可能存在的论点.我有点接受它只是一个糟糕的问题.但在阅读完答案之后,我感觉更像是我理解并给出了所有论点,甚至同意Lua没有尝试提供这些操作员. (5认同)
  • *1.*但是已经存在这种类型的运算符`:`.它用于调用函数,同时自动将您正在使用它的表作为第一个参数传递,就像`+ =`和朋友一样.*2.*这没有任何意义.为什么线分离与它有关?它的语法与普通赋值运算符相同,`=`.*3.*这听起来很清楚.你想增加所有三个. (3认同)

Rod*_*ddy 16

我想你可以把这个问题重写为

为什么不<languageX>具有<featureY><languageZ>

通常情况下,语言设计师根据他们对语言目标的看法以及他们的目标进行权衡.

在Lua的情况下,该语言旨在成为嵌入式脚本语言,因此任何使语言更复杂或可能使编译器/运行时稍微更大或更慢的更改都可能违背此目标.

如果你实现了每一个微小的功能,你最终会得到一个"厨房水槽"语言:ADA,任何人?

正如你所说,它只是语法糖.


hug*_*omg 11

Lua没有自我赋值运算符的另一个原因是表访问可能会被metatables重载以产生任意的副作用.对于自我分配,您需要选择desugar

foo.bar.baz += 2
Run Code Online (Sandbox Code Playgroud)

foo.bar.baz = foo.bar.baz + 2
Run Code Online (Sandbox Code Playgroud)

或进入

local tmp = foo.bar
tmp.baz = tmp.baz + 2
Run Code Online (Sandbox Code Playgroud)

第一个版本运行__indexmetamethod foo两次,而第二个版本只运行一次.不包括语言中的自我分配并强制您明确有助于避免这种歧义.

  • `:`是Lua中非常相似的运算符,并不像那样工作.它只调用一次`__index`,并且该值被使用两次. (7认同)
  • 第二个选项会更明智,例如“do local t=foo.bar t.baz=t.baz+2 end”。 (2认同)