1. ホーム
  2. スクリプト・コラム
  3. ルア

Luaにおけるイテレータの分析

2022-02-10 03:07:13

 イテレータとは、いわゆるコレクションやコンテナ内の要素に対して反復処理を行うための構造体である。Luaでは、これらのコレクションは通常、配列テーブルのような様々なデータ構造を作成するために使用されるものです。
一般的にイテレータ用

一般的なイテレータは、キーと値のペアのコレクションの各要素を提供します。以下は簡単な例です。

コピーコード コードは以下の通りです。
array = {"Lua", "Tutorial"}

for key,value in ipairs(array)
do
   print(key, value)
end

上記のコードを実行すると、次のような出力が得られます。

コピーコード コードは以下の通りです。
1 Lua
2 Tutorial

上記の例では、Luaが提供するデフォルトのipairsイテレーション関数を使用しています。

Luaでは、イテレータを表すのに関数を使用します。このイテレータは、機能的な状態の保持の仕方によって、大きく2種類に分かれます。

  1.     ステートレス・イテレータ
  2.     イテレータの状態

ステートレスなイテレータ

名前からわかるように、このタイプのイテレータ関数は状態を保持しない。

では、nの数の2乗を表示する簡単な関数を使って、独自のイテレータを作成する例を見てみましょう。

コピーコード コードは以下の通りです。
function square(iteratorMaxCount,currentNumber)
   if currentNumber<iteratorMaxCount
   then
      currentNumber = currentNumber+1
   return currentNumber, currentNumber*currentNumber
   end
end

for i,n in square,3,0
do
   print(i,n)
end

上記のプログラムを実行すると、次のような出力が得られます。

コピーコード コードは以下の通りです。
1 1
2 4
3 9

上記のコードは、イテレータがipairs関数で動作する方法を模倣するために若干修正することができます。以下にそれを示します。

コピーコード コードは以下の通りです。
function square(iteratorMaxCount,currentNumber)
   if currentNumber<iteratorMaxCount
   then
      currentNumber = currentNumber+1
   return currentNumber, currentNumber*currentNumber
   end
end

function squares(iteratorMaxCount)
   return square,iteratorMaxCount,0
end 

for i,n in squares(3)
do
 print(i,n)
end

上記のプログラムを実行すると、次のような出力が得られます。

コピーコード コードは以下の通りです。
1 1
2 4
3 9

イテレータの状態

イテレータは、前の例と同様に、状態を保持しない関数を使用します。この関数が呼ばれるたびに、関数に送られた2番目の変数に基づいたセットの次の要素を返します。現在の要素の状態を保持するために、クロージャが使用されます。クロージャは、異なる関数呼び出し変数の値を保持します。新しいクロージャを作るには、クロージャ自身を含む2つの関数と、クロージャの関数を作成するファクトリーを作る。

では、クロージャを使った独自のイテレーションを作成する例を見てみましょう。

コピーコード コードは以下の通りです。
array = {"Lua", "Tutorial"}

function elementIterator (collection)
   local index = 0
   local count = #collection
   -- The closure function is returned
   return function ()
      index = index + 1
      if index <= count
      then
         -- return the current element of the iterator
         return collection[index]
      end
   end
end

for element in elementIterator(array)
do
   print(element)
end

上記のプログラムを実行すると、次のような出力が得られます。

コピーコード コードは以下の通りです。
Lua
Tutorial

上の例では、要素の反復処理には別のアプローチもあり、インデックス付きのローカル外部変数を使用し、各関数が呼ばれたときにインデックスをインクリメントすることでカウントし、各コレクションの要素を返すことがわかります。

上記のように、関数にクロージャを使用するイテレータを作成することで、複数の要素を返すことができ、ループ時にそれぞれのコレクションを通過させることができるのです。