为什么Lua会以这种方式调整结果?
我正在阅读Lua参考手册,上面写着: 函数调用和vararg表达式都可以产生多个值。[…]如果表达式用作表达式列表的最后(或唯一)元素,则不会进行任何调整(除非调用包含在括号中)。在所有其他上下文中,Lua将结果列表调整为一个元素,丢弃除第一个元素外的所有值 这种选择有什么好处为什么Lua会以这种方式调整结果?,lua,Lua,我正在阅读Lua参考手册,上面写着: 函数调用和vararg表达式都可以产生多个值。[…]如果表达式用作表达式列表的最后(或唯一)元素,则不会进行任何调整(除非调用包含在括号中)。在所有其他上下文中,Lua将结果列表调整为一个元素,丢弃除第一个元素外的所有值 这种选择有什么好处 这对于其他编程语言来说很常见吗?其他允许vararg函数和多个返回值的语言通常要求更明确。他们没有像Lua那样获得第一个项目的无声快捷方式。以下是使用Lua方式进行此操作的一些可能原因: 可能最重要的原因是,可以从多个
这对于其他编程语言来说很常见吗?其他允许vararg函数和多个返回值的语言通常要求更明确。他们没有像Lua那样获得第一个项目的无声快捷方式。以下是使用Lua方式进行此操作的一些可能原因:
- 可能最重要的原因是,可以从多个值中获取显式项的数量,即使它们以
结尾。见和。对表的隐式转换将丢失此信息nil
- 您可以向
语句添加第二个值,而不会破坏向后兼容性。否则,调用代码必须更改才能访问第一个返回值return
- 有时,第二个返回值是一条错误消息。Lua允许我们通过假装函数只有一个返回值来忽略错误。(尽管这可能是不利因素,而不是有利因素。)
- 语法糖可能还有其他我没有想到的优点
local x, y, z = a()
另一方面,在没有当前规则的情况下,以下代码
local x, y, z = b(), c()
很难分析:x
、y
和z
如果返回至少3个值(c()
的返回值在这种情况下被完全删除),则可以保存b()的返回值,或者如果b()则只能保存c()
的返回值(填充nil
s)
根本不返回任何值或其各种组合。请注意,函数返回值的数量可能因环境而异
使用当前规则x
始终获取b()
的第一个返回值(这通常是最重要的)(或者如果b()
不返回任何值,则可能获取nil
),y
始终获取c()
的第一个返回值(或者nil
),和c
获取c()
或nil
的第二个返回值。非常简单,上面的第一个用例也包括在内
所以原因是,只需查看赋值,就可以更容易地破译哪个变量得到哪个返回值。函数调用也是如此,顺便说一句:
function f( x, y, z )
-- ...
end
f( b(), c() )
调整为单个值是一个很好的特性。但是Lua缺少相反的特性——保留所有的值。例如,让方括号表示保留所有值,让函数f()返回1,2,3
,然后返回f(),(f()),[f()],f()
应该返回8个值:1,1,1,2,3,1,2,3
如果b()
返回的结果数很难预测(如您所说,您必须破译它)那么为什么有人会使用赋值局部x,y,z=b(),c()
?大多数现实生活中的用例都没有这种“解密问题”。例如,有些函数返回3个值(3D点),有些函数返回2个值(某个间隔的左边界和右边界),依此类推。您还可以使用特殊运算符(b())
仅提取第一个值,如果需要,您可以编写局部x,y,z=(b()),c()
。不需要总是提取第一个值。这降低了语言的表达能力。如果你所有的函数总是返回相同数量的值,并且所有这些值都同等重要,那么这种调整功能就没有意义了。但Lua中的所有函数都不是这样。例如,许多人忘记了string.gsub
返回两个值,因为您很少需要/使用第二个值。标准库中一些设计糟糕的函数不应该成为改进语言的理由。顺便说一句,string.gsub
的第二个结果是初学者的PITA:table.insert(t,str:gsub(…)
,我希望它是两个独立的函数(gsub
和gsubcnt
)。@EgorSkriptunoff不难,但无法分析-Lua允许动态的多个返回值,而函数在语法上也是一个表达式。不仅如此,它还允许您在包含块的生存期内更改该表达式的内容,甚至可以从外部文件进行评估。所以,即使是分析也不能始终给你正确数量的返回值。@dualded-我不理解你的意思。Lua不需要在编译时预测值的数量。相反,在运行时,Lua可以接收(并在堆栈中存储)从函数返回的所有值(而不仅仅是第一个值)。