この初版はLua 5.0のために書かれました。後続のバージョンでも依然として関連性は高いものの、多少相違があります。
第4版はLua 5.3を対象にしており、Amazonおよびその他の書店で購入できます。
本を購入することで、Luaプロジェクトの支援にも役立ちます。


5.2 – 可変長引数

Luaの一部の関数は可変長引数を受け取ります。たとえば、printを1つ、2つ以上などの引数で呼び出しています。

ここで、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
パラメータリストにある3つのドット(...)は、関数が可変長引数を持つことを示します。この関数が呼び出されると、そのすべての引数が単一テーブルに収集され、関数は隠れたパラメータargとしてこれにアクセスします。これらの引数に加えて、argテーブルには、収集された引数の実際数を表す追加フィールドnがあります。

場合によっては、関数は固定パラメータに加えて可変長パラメータを持つことがあります。例を見てみましょう。式に複数の値を返す関数を記述する場合、その最初の結果のみが使用されます。しかし、場合によっては別の結果が必要になります。一般的な解決策はダミー変数を使用することです。たとえば、string.findから2番目の結果のみが必要な場合、次のコードを記述できます。

    local _, x = string.find(s, p)
    -- now use `x'
    ...
もう1つの解決策は、関数から特定のリターンを選択する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の呼び出しは常に1つの固定引数(セレクタ)と、可変長追加引数(関数の戻り値)を持つことに注意してください。この固定引数を収容するため、関数はドットの前に通常の引数を持つことができます。その後、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)を使用して別の関数を呼び出すことです。unpackargのすべての値を返します。これは別の関数に渡されます。この使用の良い例は、書式付きテキストを記述する関数です。Luaには、テキストの書式を指定する個別関数(string.format。Cライブラリのsprintf関数と同様)と、テキストを記述する関数(io.write)があります。もちろん、この2つの関数を1つの関数に簡単に結合できます。この新しい関数は、可変長の値をformatに渡す必要があるという点を除いてです。これはunpackの仕事です。

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