この初版は Lua 5.0用に書かれました。後々のバージョンに適用することは概ね可能ですが、若干の相違点があります。
第4版は Lua 5.3を対象としており、Amazonや他の書店で入手できます。
書籍を購入することで、Lua プロジェクトを支援することにもなります。


7.3 無状態のイテレータ

その名の通り、無状態のイテレータは、それ自体で状態を一切保持しないイテレータです。したがって、複数のループで同じ無状態のイテレータを使用でき、新しいクロージャーを作成するコストを回避できます。

for ループは、各イテレーションで、不変の状態と制御変数の 2 つの引数で、イテレータ関数を呼び出します。無状態のイテレータは、これら 2 つの引数のみを使用してイテレーションの次の要素を生成します。この種類のイテレータの代表的な例は ipairs で、配列内のすべての要素を反復処理します。以下に示します。

    a = {"one", "two", "three"}
    for i, v in ipairs(a) do
      print(i, v)
    end
イテレーションの状態は、走査中のテーブル(ループ中に変化しない不変の状態)と現在のインデックス(制御変数)です。ipairs とそれが返すイテレータは非常に単純なので、次の Lua で記述できます。
    function iter (a, i)
      i = i + 1
      local v = a[i]
      if v then
        return i, v
      end
    end
    
    function ipairs (a)
      return iter, a, 0
    end
Lua が for ループで ipairs(a) を呼び出すと、3 つの値を取得します。iter 関数をイテレータとして、a を不変の状態として、制御変数の初期値としてゼロを取得します。次に、Lua は iter(a, 0) を呼び出します。これにより、1, a[1] が返されます(ただし、a[1] がすでに nil の場合は除きます)。2 番目のイテレーションでは iter(a, 1) を呼び出し、2, a[2] が返され、以降は最初の nil 要素まで続行されます。

テーブル内のすべての要素を反復処理する pairs 関数は、Lua のプリミティブ関数であるイテレータ関数が next 関数であることを除けば、似ています。

    function pairs (t)
      return next, t, nil
    end
k がテーブル t のキーである next(t, k) の呼び出しは、テーブル内の次のキーを任意の順序で返します。(2 番目の戻り値として、そのキーに関連付けられた値も返します。)next(t, nil) の呼び出しは最初のペアを返します。ペアがなくなった場合、nextnil を返します。

pairs を呼び出さずに、next を直接使用するほうが好ましい人もいます。

    for k, v in next, t do
      ...
    end
for ループの式リストは 3 つの結果に調整されるため、Lua は nextt、および nil を取得します。これは、pairs(t) を呼び出したときに取得するものとまったく同じです。