回答:
簡単に言えば、イテレータは状態を保持しますが、走査可能オブジェクトは保持しません。
AにTraversable
は1つの抽象メソッドがありますforeach
。を呼び出すforeach
と、コレクションは渡された関数が保持するすべての要素を次々にフィードします。
一方、Iterable
has as abstract methodはiterator
、を返しますIterator
。を呼び出しnext
て、Iterator
選択時に次の要素を取得できます。あなたがそうするまで、それはそれがコレクションのどこにあったか、そして次は何を追跡する必要があります。
Iterable
拡張されるTraversable
ので、私はあなたがTraversable
sではないことを意味すると思いますIterable
。
Traversable
インターフェースに準拠している間は、状態を維持する必要はありませんが、インターフェースに準拠している必要がありIterator
ます。
Traversable
sはIterable
反復状態を保持しません。それはだIterator
作成されてから返されたIterable
状態を維持しています。
それを吹くと吸うの違いと考えてください。
Traversable
s foreach
またはその派生メソッドを呼び出すと、その値が一度に1つずつ関数に吹き込まれ、反復を制御できます。
でも、Iterator
返されたIterable
値を使用して、値を吸い取り、次の値に移動するタイミングを自分で制御します。
tl; dr Iterables
はTraversables
ステートフルを生成できるIterators
まず、それIterable
がの下位特性であることを知ってくださいTraversable
。
第二に、
Traversable
foreach
他のすべてで使用されるメソッドを実装する必要があります。
Iterable
iterator
他のすべてで使用されるメソッドを実装する必要があります。
たとえば、find
for の実装Traversable
はforeach
(for内包表記を介して)BreakControl
、満足のいく要素が見つかると、例外をスローして反復を停止します。
trait TravserableLike {
def find(p: A => Boolean): Option[A] = {
var result: Option[A] = None
breakable {
for (x <- this)
if (p(x)) { result = Some(x); break }
}
result
}
}
対照的に、Iterable
減算はこの実装をオーバーライドfind
し、を呼び出します。これIterator
は、要素が見つかると反復を停止するだけです。
trait Iterable {
override /*TraversableLike*/ def find(p: A => Boolean): Option[A] =
iterator.find(p)
}
trait Iterator {
def find(p: A => Boolean): Option[A] = {
var res: Option[A] = None
while (res.isEmpty && hasNext) {
val e = next()
if (p(e)) res = Some(e)
}
res
}
}
Traversable
反復のために例外をスローしないのは良いことですが、それだけがを使用して部分的に反復する唯一の方法foreach
です。
1つの観点から見ると、を使用してIterable
簡単に実装できますが、実際にを使用して実装することはできません。foreach
iterator
iterator
foreach
要約するとIterable
、ステートフルを介して反復を一時停止、再開、または停止する方法を提供しますIterator
。を使用するとTraversable
、それはオールオアナッシング(フロー制御の例外を除く)になります。
ほとんどの場合それは問題ではなく、より一般的なインターフェースが必要になります。ただし、反復に対してよりカスタマイズされた制御が必要な場合はIterator
、から取得できるが必要になりますIterable
。
ダニエルの答えはいいですね。それを自分の言葉で説明できるか見てみましょう。
そのため、Iterableはイテレータを提供し、要素を1つずつ(next()を使用して)トラバースし、好きなように停止および移動できます。これを行うには、イテレータが要素の位置への内部「ポインタ」を保持する必要があります。ただし、Traversableを使用すると、停止せずにすべての要素を一度にトラバースできます。
Range(1、10)のようなものは、Traversableとして状態として2つの整数のみを持つ必要があります。しかし、IterableとしてのRange(1、10)は、状態に3つの整数を使用する必要があるイテレータを提供します。そのうちの1つはインデックスです。
TraversableはfoldLeft、foldRightも提供することを考えると、そのforeachは既知の固定された順序で要素をトラバースする必要があります。したがって、Traversableのイテレータを実装することが可能です。たとえば、def iterator = toList.iterator
Traversable
でのScala 2.13(それはまだのための非推奨別名として保持されてIterable
2.14まで)