イテレータ

**イテレータ**（）とは、プログラミング言語において配列やそれに類似する集合的データ構造（コレクションあるいはコンテナ）の各要素に対する繰り返し処理の抽象化である。実際のプログラミング言語では、オブジェクトまたは文法などとして現れる。JISでは**反復子**（はんぷくし）と翻訳されている。

ジェネレータ (プログラミング) の記事も参照のこと。

## 種類

### 内部イテレータ

## 各言語における例
### C++
C++では、STLが外部イテレータの枠組みを定義している。この枠組みはポインタと構文上の互換性を持つよう定められているため、ポインタを用いるコードと同等のコードでイテレータを使用することができる。


```cpp
template<typename InputIterator>
void printall(InputIterator first, InputIterator last)
{
    for (; first != last; ++first)
    {
        std::cout << *first << std::endl;
    }
}
```


C++ではイテレータの種類によって使用できる演算子に違いがある。例えば、`std::vector`コンテナのイテレータのような「ランダムアクセスイテレータ」と、`std::list`コンテナのイテレータのような「双方向イテレータ」は、共にインクリメント/デクリメント演算子を用いて直後/直前（次/前）の要素を指すことができる。しかし、任意の幅の加算/減算はランダムアクセスイテレータでのみ定義されている。ランダムアクセスイテレータは双方向イテレータの一種だが、イテレータの進行操作は定数時間で実行できることが要件として定められている。`std::list`コンテナの要素は、前後の要素へのポインタしか保持していないためシーケンシャルアクセスしかできず、イテレータの進行操作が定数時間で実行できないため、ランダムアクセスイテレータをサポートすることができない。

もともとC++のイテレータはテンプレートを利用した静的ダックタイピングによるものであり、各イテレータの要件定義は規格で文書化されていたものの、言語構文としてはサポートされていなかった。しかし、C++20ではコンセプト (`concept`) をサポートしたことにより、`std::random_access_iterator`や`std::bidirectional_iterator`などの形で満たすべき要件をコードとして書き下すことが可能になった。

### Delphi
Delphiでは、バージョン2005より`for-in`構文によるイテレータがある。ユーザーによるイテレータは`MoveNext`メソッドや`Current`プロパティを任意のクラス等に実装することで定義でき、型に厳格なPascal系言語ながらこれらを実装するだけで`for-in`により認識されるというダックタイピングにも似た仕組みとなっている。


```delphi
for item in items do
  Writeln(item);
```


### Java
Javaでは、インターフェイス族を実装するオブジェクトを外部イテレータとして扱うことができる。Java 1.5以降の`Iterator`はジェネリクスに対応している。


```java
import java.util.*;
// ...

final List list = new ArrayList();
// Java 1.5 以降は以下のように書くこともできる。
//final List<Object> list = new ArrayList<Object>();
// Java 1.7 以降は以下のように書くこともできる。
//final List<Object> list = new ArrayList<>();

list.add("hoge");
list.add(Integer.valueOf(100));
list.add(Double.valueOf(-0.5));

final Iterator it = list.iterator();
// Java 1.5 以降は以下のように書くこともできる。
//final Iterator<Object> it = list.iterator();

while (it.hasNext()) {
    final Object obj = it.next();
    System.out.println(obj.toString());
}
```


Java 1.5以降では、インターフェイスを実装すると、拡張for文（foreach文）の対象にすることができる。

```java
// java.util.List は Iterable を実装している。
for (final Object obj : list) {
    System.out.println(obj.toString());
}
```


### Perl
Perlには、`foreach`、`each` といった繰り返しのキーワードがある。
他に、Tie機能（変数操作のオーバーロード）でユーザーデータに対するイテレータを定義できる。

```perl
# foreachを使った例。配列・リストに対する反復。
foreach my $element(@array){
    print $element, "\n";
}
```



```perl
# eachを使った例。ハッシュ（連想配列）に対する反復。
while(my($key, $value) = each %hash){
    print "$key=$value\n";
}
```


### PHP
PHPではIteratorインターフェイスを実装することにより、任意のイテレータを定義することができる。Iteratorインターフェイスを実装したオブジェクトを`foreach`や`while`で使用することで反復を行うことができる。
また、配列はIteratorインターフェイスを暗黙に実装する。


```php
# foreachを使った例。配列・連想配列・オブジェクト等に対し全く同じように使用できる。
foreach ( $elements as $key=>$value ){
    print $key . "=" . $value . " \n";
}
```


### Python
Pythonは次の要素を返す`__next__()`メソッドを持つオブジェクトを外部イテレータとして使う。コンテナオブジェクトの`__iter__()`メソッドがイテレータを返す。（便宜上、イテレータの`__iter__()`は自身を返す）

通常のプログラミングでは、`obj.__iter__()`のように直接呼ぶのではなく、組込み関数iterを使って`iter(obj)`のようにする。同様に、通常の用法で呼ぶことを前提とした場合は`__next__()`ではなく`next()`を使う。for文（Foreach文）はイテレータが使える場合はイテレータを使うが、そうでないコンテナオブジェクトに対しては直接、`__getitem__()`メソッドにより要素を取得し繰返しを実行する。


```python
cont = iteratable_container()

# イテレータを直接使う
it = iter(cont)
while 1:
    try:
        print it.next()
    except StopIteration:
        # 要素が残っていないならば、
        # next()はStopIteration例外を発生させる
        break

# for文で使う
for element in cont:
    print element
```


また、Pythonには一種のコルーチンを記述できるジェネレータもある。ジェネレータはイテレータを返す関数で、yield文により、`__next__()`で実行される手続きを次々と記述できる。


```python
def fruit_generator():
    yield 'banana'  # 最初の __next__() によりここまで実行され 'banana' を返す
    yield 'apple'  # 次の __next__() によりここまで実行され 'apple' を返す
    yield 'orange'  # 3回目の __next__() によりここまで実行され 'orange' を返す

for fruit in fruit_generator():
    print(fruit)

it = fruit_generator()
print(next(it))
print(next(it))
print(next(it))
print(next(it))  # この行で StopIteration 例外になる
```


### Ruby
RubyではEnumerableが、eachなどのイテレートするメソッドを持っている内部イテレータである。メソッド呼出しに `{ ... }` という書式で「ブロック」を書くと、その中の手続きが繰返し実行される。


```ruby
class MyObj
  def my123
    yield 1
    yield 2
    yield 3
  end
end

arr = ["a", "b", "c"]
arr.each do |x|
  p x
end

obj = MyObj.new
obj.my123 do |x|
  p x
end
```


### .NET言語
C#、VB.NETなどの.NET Frameworkに準拠する.NET言語において、反復子 (iterator) は値の順序付き列を産出 (yield) する文のブロック（狭義ではyield文を含むメソッド）を意味する。これを反復子ブロック (iterator block) とも呼ぶ。また、コレクションに対する列挙操作を行なう機能を提供するための媒介インターフェイスを列挙子 (enumerator) と呼び、`IEnumerator`インターフェイスによって表す。`IEnumerator`インターフェイスは`MoveNext()`メソッドを定義しており、このメソッドを使用することによりコレクション中の次の要素に進むと同時に、コレクションの末尾に到達するかどうかを判定する。`Current`プロパティを使用することによってコレクション内部の要素を取得する。イテレータを最初の要素に戻す方法として`Reset()`メソッドが定義されるが、常に使用可能であるとは限らない。

列挙子を得るには通例`IEnumerable`インターフェイスを実装するオブジェクトの`GetEnumerator()`メソッドを呼び出す。一般的にコレクション クラスはこの`IEnumerable`インターフェイスを実装する。`GetEnumerator()`を明示的に呼び出さず、`[[foreach文|foreach]]`文を代わりに使用することもできる（`GetEnumerator()`はコンパイラによって暗黙的に呼び出される）。`IEnumerator`および`IEnumerable`インターフェイスは、.NET 2.0でジェネリック版 (`System.Collections.Generic`) として拡張された。

#### C# 2.0

```csharp
// 明示的な使い方
IEnumerator<MyType> iter = list.GetEnumerator();
while (iter.MoveNext()) {
    Console.WriteLine(iter.Current);
}

// 暗黙的な使い方
foreach (MyType value in list) {
    Console.WriteLine(value);
}
```


#### Visual Basic 8.0

```vbnet
' 明示的な使い方
Dim iter As IEnumerator(Of MyType) = list.GetEnumerator()
Do While iter.MoveNext()
    Console.WriteLine(iter.Current)
Loop
 
' 暗黙的な使い方
For Each value As MyType In list
    Console.WriteLine(value)
Next value
```


#### yield文
C# 2.0およびVB.NET 11は反復子の形でジェネレータ (generator) をサポートする。ジェネレータは`IEnumerator`または`IEnumerable`を返すよう宣言されたメソッドであるが、オブジェクトインスタンスを返す代わりに要素のシーケンスを生成するための`yield return`ステートメントを使用する。yieldステートメントを用いて記述されたジェネレータはコンパイラによって、適切なインターフェイスを実装する新しいクラスに変換される。ただし、ジェネレータ（反復子）は`IEnumerator.Reset()`メソッドをサポートしない。


```csharp
// 反復子の記述例。
static IEnumerable<int> MyIteratorMethod() {
    yield return 1;
    yield return -1;
    yield return 0;
    yield break;
}

IEnumerable<int> elements = MyIteratorMethod(); // この時点では、まだメソッドの本体は実行されない。

// 列挙によりメソッドの本体が順次「遅延実行」される（中断と再開を繰り返す）。
foreach (int element in elements) {
    Console.WriteLine(element);
}
```



```vbnet
Shared Iterator Function MyIteratorMethod() As IEnumerable(Of Integer)
    Yield 1
    Yield -1
    Yield 0
    Return
End Function

Dim elements As IEnumerable(Of Integer) = MyIteratorMethod()

For Each element As Integer In elements
    Console.WriteLine(element)
Next
```


### D言語
D言語では、標準ライブラリにレンジ (Range) というイテレータが定義されており、規定されたインターフェイスを持っているオブジェクトなら何でもレンジとして扱うことができる。


```d
foreach (item; range)
	writeln(item);
```


## 脚注

### 注釈

### 出典

## 関連項目
*ループ (プログラミング)
*Foreach文
*Iterator パターン
*コンテナ (データ型)
*カーソル (データベース)
*fgetc