Расширение 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
}
К сожалению, быстрый просмотр стандартной библиотеки не обнаруживает функции чередования потоков. Достаточно легко написать один
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
}
}
}
Это создает поток, который периодически чередуется между двумя потоками, выбирая следующий результат из соответствующего и затем устанавливая его состояние для следующей выборки. Обратите внимание, что это чередование работает только для бесконечных потоков, и нам понадобится более умный для обработки потоков, которые могут закончиться, но для проблемы это нормально.