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)
你可以将自我赋值运算符限制为单一赋值,但是你刚刚添加了一个人们必须知道的奇怪角落案例.
综上所述,自我赋值运算符非常有用,值得处理上述问题.
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两次,而第二个版本只运行一次.不包括语言中的自我分配并强制您明确有助于避免这种歧义.