我有这个代码,我想让Stream停止迭代并获得累积的结果。基本上,迭代基于errorLimit number
sealed trait Ele
case class FailureEle() extends Ele
case class SuccessEle() extends Ele
type EitherResult = Either[IndexedSeq[Ele], Seq[FailureEle]]
def parse(process: Process[Task, Ele], errorLimit: Int): EitherResult = {
val errorAccumulator = new ListBuffer[FailureEle]
val taskProcess = process.map(t => {
t match {
case x: FailureEle => errorAccumulator += x
case _ =>
}
t
}).takeWhile(_ => !(errorAccumulator.size == errorLimit))
val voSeq = taskProcess.runLog.run
if (errorAccumulator.isEmpty) {
Left(voSeq)
} else {
Right(errorAccumulator)
}
}
val result = Seq(FailureEle(), SuccessEle(), FailureEle(), SuccessEle(), SuccessEle(), FailureEle(), SuccessEle())
val adaptor = new SeqAdaptor[Ele](result)
val process: Process[Task, Ele] = Process
.repeatEval(Task {adaptor.next()}).takeWhile(t => !t.shouldStop).map(_.get)
parse(process, 1).isRight //no SuccessEle will be iterated
parse(process, 2).isRight //only one SuccessEle will be iterated
parse(process, 3).isRight //the last one SuccessEle will not be iterated
它正在运行,但有几个问题我想重构解析方法以使其更具功能性:
ListBuffer是一种必要的方式
takeWhile条件没有逻辑来检查当前元素,它仍然使用ListBuffer结果
所以我想知道是否有一种尾递归方式来使用ListBuffer替换命令式方法。
答案 0 :(得分:0)
scan
可能不够好,但有效
sealed trait Ele
case class FailureEle(e: Throwable) extends Ele
case class SuccessEle(r: String) extends Ele
def parse(p: Process[Task, Ele], error: Int): Process[Task, (Seq[SuccessEle], Seq[FailureEle])] = {
p.scan(Seq[SuccessEle]() -> Seq[FailureEle]()) { (r, e) =>
val (s, f) = r
e match {
case fail: FailureEle =>
s -> (f :+ fail)
case succ: SuccessEle =>
(s :+ succ) -> f
}
}.dropWhile { case (succ, fail) => fail.size < error }.take(1)
}
def test() {
def randomFail = {
val nInt = scala.util.Random.nextInt()
println("getting" + nInt)
if(nInt % 5 == 0 )
FailureEle(new Exception("fooo"))
else
SuccessEle(nInt.toString)
}
val infinite = Process.repeatEval(Task.delay(randomFail))
val r = parse(infinite, 3).runLast.run
println(r)
}