この初めに版は、Lua 5.0 用に書かれました。後のバージョンでもほとんどは関連がありますが、一部相違があります
第 4 版では Lua 5.3 を対象に、Amazon やその他の書店で購入できます。
この本を買うことで、Lua プロジェクトをサポートすることにもつながります。


7.5 – 本物のイテレータ

「イテレータ」という名称は少し誤解を招きます。これは、このイテレータはイテレート(反復)しないためです。イテレートするのは for ループです。イテレータは単にイテレーションに対する連続する値を提供するだけです。より良い名前は「ジェネレータ」かもしれませんが、「イテレータ」は Java など、他の言語ですでに確固とした地位を築いています。

しかし、イテレータをイテレーションを実行する別の方法があります。そのようなイテレータを使用する場合は、ループは書きません。代わりに、イテレータを、各イテレーションでイテレータが実行する必要がある処理を記述する引数とともに呼び出します。より具体的には、イテレータは、ループ内で呼び出す関数を引数として受け取ります。

具体的な例として、このスタイルを使用して allwords イテレータをさらに書き直してみましょう

    function allwords (f)
      -- repeat for each line in the file
      for l in io.lines() do
        -- repeat for each word in the line
        for w in string.gfind(l, "%w+") do
          -- call the function
          f(w)
        end
      end
    end
このようなイテレータを使用するには、ループ本体を関数として指定する必要があります。各単語を出力する場合、ただ単に print を使用します
    allwords(print)
より頻繁に、匿名関数を本体として使用します。たとえば、次のコードフラグメントは、入力ファイルに「hello」という単語が何回出現するかをカウントします
    local count = 0
    allwords(function (w)
      if w == "hello" then count = count + 1 end
    end)
    print(count)
前のイテレータスタイルで記述した場合、同じタスクは特に変わりません
    local count = 0
    for w in allwords() do
      if w == "hello" then count = count + 1 end
    end
    print(count)

本物のイテレータは、言語に for ステートメントがなかった、古いバージョンの Lua でよく使用されていました。ジェネレータスタイルのイテレータとはどのように比較するのでしょうか?どちらのスタイルもほぼ同じオーバーヘッドがあります。イテレーションあたり 1 つの関数呼び出しです。一方、この 2 番目のスタイルを使用してイテレータを作成する方が簡単です(ただし、この手軽さはコルーチンで回復できます)。その一方で、ジェネレータスタイルはより柔軟です。最初に、2 つ以上の並列イテレーションを許可します。(たとえば、2 つのファイルを単語ごとに比較しながらイテレートする問題を考えてみます)次に、イテレータ本体内で breakreturn を使用できます。(本物のイテレータでは、return はイテレーションを実行している関数からではなく、匿名関数から返されます。)