第一版是针对 Lua 5.0 编写的。虽然在很大程度上仍然适用于更高版本,但有一些区别。
第四版针对 Lua 5.3,可在 亚马逊 和其他书店购买。
购买本书,您还将帮助支持 Lua 项目


5.2 – 可变数量的参数

Lua 中的一些函数接收可变数量的参数。例如,我们已经使用一个、两个或更多参数调用过 print

现在假设我们想在 Lua 中重新定义 print:也许我们的系统没有 stdout,因此 print 不会打印其参数,而是将它们存储在全局变量中以供以后使用。我们可以用 Lua 编写这个新函数,如下所示

    printResult = ""
    
    function print (...)
      for i,v in ipairs(arg) do
        printResult = printResult .. tostring(v) .. "\t"
      end
      printResult = printResult .. "\n"
    end
参数列表中的三个点(...)表示该函数具有可变数量的参数。当调用此函数时,其所有参数都将收集到一个表中,函数以隐藏参数 arg 的形式访问该表。除了这些参数外,arg 表还有一个额外的字段 n,其中包含收集到的实际参数数量。

有时,一个函数有一些固定参数和一些可变参数。我们来看一个示例。当我们编写一个将多个值返回到表达式中的函数时,只会使用其第一个结果。但是,有时我们想要另一个结果。一个典型的解决方案是使用哑变量;例如,如果我们只想要 string.find 的第二个结果,我们可以编写以下代码

    local _, x = string.find(s, p)
    -- now use `x'
    ...
另一种解决方案是定义一个 select 函数,该函数从函数中选择一个特定返回
    print(string.find("hello hello", " hel"))         --> 6  9
    print(select(1, string.find("hello hello", " hel"))) --> 6
    print(select(2, string.find("hello hello", " hel"))) --> 9
请注意,对 select 的调用始终有一个固定参数,即选择器,以及可变数量的额外参数(函数的返回)。为了适应这个固定参数,函数可以在点之前具有常规参数。然后,Lua 将前几个参数分配给那些参数,只有额外的参数(如果有)才会传递给 arg。为了更好地说明这一点,假设有一个类似这样的定义
    function g (a, b, ...) end
然后,我们有从参数到参数的以下映射
    CALL            PARAMETERS
       
    g(3)             a=3, b=nil, arg={n=0}
    g(3, 4)          a=3, b=4, arg={n=0}
    g(3, 4, 5, 8)    a=3, b=4, arg={5, 8; n=2}

使用那些常规参数,select 的定义非常简单

    function select (n, ...)
      return arg[n]
    end

有时,具有可变数量参数的函数需要将所有参数传递给另一个函数。它所要做的就是使用 unpack(arg) 作为参数来调用另一个函数:unpack 将返回 arg 中的所有值,这些值将传递给另一个函数。此用途的一个很好的例子是编写格式化文本的函数。Lua 提供了单独的函数来格式化文本(string.format,类似于 C 库中的 sprintf 函数)和编写文本(io.write)。当然,可以轻松地将这两个函数合并为一个函数,只不过这个新函数必须将可变数量的值传递给 format。这是 unpack 的一项工作

    function fwrite (fmt, ...)
      return io.write(string.format(fmt, unpack(arg)))
    end