Skip to content

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