汎用forの使い方

最近、ゲームなどに採用されているLua言語を勉強して見た。

そこで気が付いたのが、汎用for(generic for)に関する具体的な説明が見当たらないことだ。
これではせっかく存在する機能が見捨てられてしまうと思ったので、ここで説明して見ようと思う。

汎用forはイテレータiterator)を呼び出すものらしい。
マニュアルに記載されている構文は以下の通り。

stat ::= for Name {`,' Name} in explist1 do block end

何のことやらさっぱり分からない。
マニュアルで、上記構文の下に記載されている等価コードと注意書きを良く読んで考えると、上記構文は以下の書式となる。

for <変数リスト> in <イテレータ>, <汎用パラメータ>, <ループ初期値> do
    <ブロック>
end
  • イテレータ
    第1引き数に「汎用パラメータ」、第2引き数に初回呼び出し時は「ループ初期値」、2回目以降は前回呼び出し時の第1戻り値を受け取る関数である。ループを終了するときは第1戻り値でnilを返す。
  • 汎用パラメータ
    イテレータの第1引き数であり、イテレータが理解できれば何でも良い。
  • ループ初期値
    1回目にイテレータが呼び出されるときの第2引き数であり、イテレータが理解できれば何でも良い。
  • 変数リスト
    イテレータの戻り値を受け取る変数のリストで、第1変数の値は次のイテレータを呼び出す時の第2引き数となる。
  • ブロック
    言うまでもないが、ループ内の処理を行う任意のプログラムである。

以下に例を示す。

function iter(parm, val)
    print("parm=", parm, "val=", val)
    if val >= 5 then
        return nil
    end
    return val + 1
end

for i in iter, nil, 0 do
    print("i=", i)
end

出力結果は以下の通り。

parm=   nil     val=    0
i=      1
parm=   nil     val=    1
i=      2
parm=   nil     val=    2
i=      3
parm=   nil     val=    3
i=      4
parm=   nil     val=    4
i=      5
parm=   nil     val=    5


テーブルの内容を表示するには、以下のようにnext関数を使用する。

array = {a = 1, b = 2, c = 3}
key, val = next(array, nil)
while key do
    print(key, "=", val)
    key, val = next(array, key)
end


next関数の仕様を良く見ると、イテレータそのものである。

array = {a = 1, b = 2, c = 3}
for key, val in next, array, nil do
    print(key, "=", val)
end


ちなみに、ZaurusLuaはmoyashiさんがここに公開している。