Iterator の拡張は、おそらく実際に必要な作業よりも多くの作業です。少しロールバックしましょう。
タイプ MyAlgorithm1 のステートフル オブジェクトがあります。
val alg1 = new MyAlgorithm1(args)
ここで、状態を変更して何らかの値を返す関数を繰り返し呼び出したいとします。これは、オブジェクトに Iterator を実装させるのではなく、反復を処理する新しいオブジェクトを作成することによってモデル化するのが最適です。Scala 標準ライブラリでおそらく最も簡単なのは Stream です。これは、アルゴリズムから結果のストリームを作成するオブジェクトです。
val alg1Stream:Stream[Step] = Stream.continually(alg1.next())
そのストリームから繰り返し結果を取得したい場合は、次のように簡単です
for(step<-alg1Stream){
// do something
}
または同等に
alg1Stream.forEach{
//do something
}
ここで、myAlgorithm2 もストリームとしてカプセル化したとします。
val alg2=new MyAlgorithm2(args)
val alg2Stream:Stream[Step] = Stream.continually(alg2.next())
次に、ストリームをインターリーブする方法が必要です。
for(step<-interleave(alg1Stream, algStream2)){
// do something
}
悲しいことに、標準ライブラリをざっと見てみると、Stream インターリーブ機能がないことがわかります。簡単に1つ書ける
def interleave[A](stream1:Stream[A], stream2:Stream[A]):Stream[A] ={
var str1 = stream1
var str2 = stream2
var streamToUse = 1
Stream.continually{
if(streamToUse == 1){
streamToUse = 2
val out = str1.head
str1 = str1.tail
out
}else{
streamToUse = 1
val out = str2.head
str2 = str1.tail
out
}
}
}
これにより、2 つのストリームを交互に繰り返し使用するストリームが構築され、適切な結果から次の結果がフェッチされ、次のフェッチのためにその状態が設定されます。このインターリーブは無限ストリームに対してのみ機能することに注意してください。終了する可能性のあるストリームを処理するには、より賢いものが必要ですが、問題のためにはそれで問題ありません。