3.4.12 - 表达式列表、多重返回以及相应调整
函数调用和可变参数表达式的结果都可以是多个值。这些表达式被称为多重表达式(multires expressions)。
当一个多重表达式被用作表达式列表的最后一个元素时,其所有的结果值都被添加到由表达式列表生成的值列表中。注意在表达式列表中的单一表达式也视为列表中的最后一个表达式(即单一列表)。
这些是Lua视为表达式列表的地方:
- return语句,例如 return e1, e2, e3(参见3.3.4)。
- 表的构造语句,例如 {e1, e2, e3}(参见3.4.9)。
- 函数调用的形参,例如 foo(e1, e2, e3)(参见3.4.10)。
- 多重赋值语句,例如 a , b, c = e1, e2, e3(参见3.3.3)。
- 局部声明,例如 local a , b, c = e1, e2, e3(参见3.3.7)。
- for循环通用形式的初始化变量,例如 for k in e1, e2, e3 do ... end(参见3.3.5)。
在后四种情况中,表达式列表的值列表已经会被调整到合适的长度:非可变参数函数的参数个数(参见3.4.11)、多重赋值和局部声明的变量个数、以及上述for循环通用形式中的那几个值的个数4。这里的调整遵循这些规则:如果存在多于所需要的值,那么额外的将被抛弃;如果所有的值比所需的少,那么会使用nil来扩展列表。当表达式列表最后也是个多重表达式时,此多重表达式的所有值将会在调整之前进入值列表。
当一个多重表达式在表达式列表中并不是最后一个元素时,或在一个被语法视为单一表达式的位置中,Lua会将表达式的结果列表调整为单个元素。举个特殊的例子,语法将单一表达式视作其在一对括号内;因此,在多重表达式外加上括号会直接强制生成单个结果。
我们很少在一个被语法视为单一表达式的地方使用多重表达式。(通常更简单的方式是在可变部分之前添加并使用常规参数。)当有这样的需求时,我们推荐将多重表达式赋值给一个单独的变量然后在此处使用。
这里是一些使用多重表达式的例子。无论如何,当构造语句中需要“第n个结果”然而并没有时,都使用nil。
lua
print(x, f()) -- 打印x和f()的所有结果
print(x, (f())) -- 打印x和f()的第一个结果
print(f(), x) -- 打印f()的第一个结果和x
print(1 + f()) -- 打印f()的第一个结果加1
local x = ... -- x为可变参数中的第一个值
x,y = ... -- x为可变参数中的第一个值
-- y为可变参数中的第二个值
x,y,z = w, f() -- x为可变参数中的第一个值
-- y为f()的第一个结果
-- z为f()的第二个结果
x,y,z = f() -- x为f()的第一个结果
-- y为f()的第二个结果
-- z为f()的第三个结果
x,y,z = f(), g() -- x为f()的第一个结果
-- y为g()的第一个结果
-- z为g()的第二个结果
x,y,z = (f()) -- x为f()的第一个结果,y和z都为nil
return f() -- 返回f()的所有结果
return x, ... -- 返回x和所接收到的所有可变参数
return x,y,f() -- 返回x、y、以及f()的所有结果
{f()} -- 创建一个列表,其中是f()的所有结果
{...} -- 创建一个列表,其中是接收到的所有可变参数
{f(), 5} -- 创建一个列表,其中是f()的第一个结果和数字5