この質問 を見ましたが、それでもIterableとTraversableの特性の違いを理解していません。誰か説明できますか?
簡単に言えば、イテレータは状態を保持しますが、トラバーサルは保持しません。
Traversable
には、foreach
という抽象メソッドが1つあります。 foreach
を呼び出すと、コレクションは、渡された関数に保持しているすべての要素を次々に送ります。
一方、Iterable
には、iterator
を返す抽象メソッドIterator
があります。 next
でIterator
を呼び出して、選択したときに次の要素を取得できます。それまでは、コレクション内のどこにあるのか、次に何をするのかを追跡する必要があります。
吹くと吸うの違いと考えてください。
Traversable
s foreach
、またはその派生メソッドを呼び出すと、値を一度に1つずつ関数に吹き込むため、反復を制御できます。
ただし、Iterator
によって返されるIterable
を使用すると、値を削除して、次の値にいつ移動するかを自分で制御できます。
tl; drIterables
は、ステートフルTraversables
を生成できるIterators
である
まず、Iterable
がTraversable
のサブトレイトであることを知ってください。
第二に、
Traversable
には、他のすべてで使用されるforeach
メソッドの実装が必要です。
Iterable
には、他のすべてで使用されるiterator
メソッドの実装が必要です。
たとえば、find
のTraversable
の実装では、foreach
を使用して(理解のために)、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
だけを使用する場合に部分的に反復する唯一の方法です。
Iterable
を使用して簡単にforeach
を実装できますが、実際にiterator
を実装することはできないため、1つの観点から、iterator
はより要求の厳しい強力な特性です。 foreach
を使用します。
要約すると、Iterable
は、ステートフルIterator
を介して反復を一時停止、再開、または停止する方法を提供します。 Traversable
を使用すると、すべてまたは何もありません(フロー制御の例外はありません)。
ほとんどの場合、それは重要ではなく、より一般的なインターフェイスが必要になります。しかし、繰り返しをさらにカスタマイズして制御する必要がある場合は、Iterator
から取得できるIterable
が必要になります。
ダニエルの答えはいいですね。自分の言葉で表現できるかどうか見てみましょう。
したがって、Iterableはイテレータを提供できます。イテレータを使用すると、要素を一度に1つずつトラバースし(next()を使用)、必要に応じて停止して実行できます。そのためには、イテレータは要素の位置への内部「ポインタ」を保持する必要があります。ただし、Traversableは、停止することなくすべての要素を一度にトラバースするメソッドforeachを提供します。
Range(1、10)のようなものは、Traversableとして状態として2つの整数のみを持つ必要があります。しかし、IterableとしてのRange(1、10)は、状態に3つの整数を使用する必要があるイテレータを提供します。その1つはインデックスです。
TraversableはfoldLeft、foldRightも提供することを考慮すると、foreachは既知の固定された順序で要素をトラバースする必要があります。したがって、Traversableのイテレータを実装することが可能です。例えば。 def iterator = toList.iterator