Lua的操作符,为什么没有定义+=,-=等操作符?

这是我曾经有些烦恼但从未找到答案的问题。

然而,我想至少问一下这个问题,也许有人可以解释。

基本上,我所使用的很多语言都利用语法糖来写(使用 C++ 的语法):

int main() {
    int a = 2;
    a += 3; // a=a+3
}

而在 lua 中,+=未定义,因此我必须编写a=a+3,这再次涉及到语法糖。当使用一个更具“意义”的变量名,如:“bleed_damage_over_time”时,编写变得繁琐:

bleed_damage_over_time = bleed_damage_over_time + added_bleed_damage_over_time

而不是:

bleed_damage_over_time += added_bleed_damage_over_time

因此,我想知道的不是如何解决这个问题,如果没有好的解决方案,我当然会对听到它感兴趣;而是为什么 lua 没有实现这种语法糖。

点赞
用户1737
用户1737

我认为你可以将这个问题重写为:

为什么<languageX>没有来自<languageZ><featureY>

通常这是语言设计师基于他们对语言目的和目标的愿景所做出的权衡。

在Lua的情况下,该语言旨在成为一种嵌入式脚本语言,因此,任何使语言变得更复杂或潜在使编译器/运行时稍微变大或变慢的更改都可能与此目标相矛盾。

如果您实现每一个微小的功能,您最终可能会得到一个“厨房水槽”语言:ADA

正如您所说,这只是一种语法糖。

2013-11-20 09:32:48
用户9457
用户9457

这只是我的猜测,但是:

1. 在单遍编译器中实现这很难

Lua 的字节码编译器是实现为单遍递归下降解析器的,它会立即生成代码。它不会解析为单独的 AST 结构,然后在第二遍转换为字节码。

这就对语法和语义造成了一些限制。特别是,需要任意前瞻或前向引用的任何内容在这个模型中真的很难得到支持。这意味着赋值已经很难解析了。例如:

foo.bar.baz = "value"

当你解析 foo.bar.baz 时,你并不意识到你实际上正在解析一个赋值,在你已经解析并生成了该代码之后,才会遇到 =。由于这个原因,Lua 的编译器处理赋值处理需要很高的复杂性。

支持自赋值将使这更加困难。例如:

foo.bar.baz += "value"

需要被转换为:

foo.bar.baz = foo.bar.baz + "value"

但是当编译器遇到 = 时,它已经忘记了 foo.bar.baz。这是可能的,但不是容易的。

2. 它可能与语法不兼容

Lua 实际上在语法中没有任何语句或行分隔符。空格被忽略,没有必须的分号。你可以这样做:

io.write("one")
io.write("two")

或者:

io.write("one") io.write("two")

Lua 对这两种都同样满意。保持这样的语法无歧义是棘手的。我不确定,但自赋值运算符可能会使其更加困难。

3. 它与多重赋值不兼容

Lua 支持多重赋值,例如:

a, b, c = someFnThatReturnsThreeValues()

如果你尝试这样做,甚至我都不确定它的含义:

a, b, c += someFnThatReturnsThreeValues()

你可以将自赋值运算符限制为单一赋值,但这样只是增加了一个人们需要知道的奇怪情况。

考虑到所有这些,很明显自赋值运算符是否有足够的用处值得处理以上问题还不清楚。

2013-12-03 21:47:45
用户90511
用户90511

另一个 Lua 没有自赋值运算符的原因是,表访问可以被重载为元表以产生任意的副作用。对于自赋值,你需要选择对以下代码进行解糖:

foo.bar.baz += 2

解糖为

foo.bar.baz = foo.bar.baz + 2

local tmp = foo.bar
tmp.baz = tmp.baz + 2

第一种版本会两次运行 foo__index 元方法,而第二种只会运行一次。不在语言中包含自赋值并强制明确说明可以帮助避免这种歧义。

2014-01-03 16:22:31