gpt4 book ai didi

exception - 在 Scala 中出现异常时重启迭代器

转载 作者:行者123 更新时间:2023-12-02 07:50:40 24 4
gpt4 key购买 nike

我有一个迭代器(实际上是一个 Source.getLines),它从 URL 读取无限数据流。当出现连接问题时,迭代器有时会抛出 java.io.IOException。在这种情况下,我需要重新连接并重新启动迭代器。我希望它是无缝的,这样迭代器对消费者来说就像一个普通的迭代器,但在必要时它会自行重启。

例如,我希望看到以下行为:

scala> val iter = restartingIterator(() => new Iterator[Int]{
var i = -1
def hasNext = {
if (this.i < 3) {
true
} else {
throw new IOException
}
}
def next = {
this.i += 1
i
}
})
res0: ...

scala> iter.take(6).toList
res1: List[Int] = List(0, 1, 2, 3, 0, 1)

我有一个解决这个问题的部分方法,但它会在某些极端情况下失败(例如,重启后第一个项目上的 IOException)并且它非常难看:

def restartingIterator[T](getIter: () => Iterator[T]) = new Iterator[T] {
var iter = getIter()
def hasNext = {
try {
iter.hasNext
} catch {
case e: IOException => {
this.iter = getIter()
iter.hasNext
}
}
}
def next = {
try {
iter.next
} catch {
case e: IOException => {
this.iter = getIter()
iter.next
}
}
}
}

我一直觉得有更好的解决方案,也许是 Iterator.continuallyutil.control.Exception 或类似的组合,但我做不到想不通。有什么想法吗?

最佳答案

这与您使用 scala.util.control.Exception 的版本相当接近:

def restartingIterator[T](getIter: () => Iterator[T]) = new Iterator[T] {
import util.control.Exception.allCatch
private[this] var i = getIter()
private[this] def replace() = i = getIter()
def hasNext: Boolean = allCatch.opt(i.hasNext).getOrElse{replace(); hasNext}
def next(): T = allCatch.opt(i.next).getOrElse{replace(); next}
}

出于某种原因,这不是尾递归,但可以通过使用稍微更冗长的版本来修复它:

def restartingIterator2[T](getIter: () => Iterator[T]) = new Iterator[T] {
import util.control.Exception.allCatch
private[this] var i = getIter()
private[this] def replace() = i = getIter()
@annotation.tailrec def hasNext: Boolean = {
val v = allCatch.opt(i.hasNext)
if (v.isDefined) v.get else {replace(); hasNext}
}
@annotation.tailrec def next(): T = {
val v = allCatch.opt(i.next)
if (v.isDefined) v.get else {replace(); next}
}
}

编辑:util.control.ExceptionIterator.continually 有一个解决方案:

def restartingIterator[T](getIter: () => Iterator[T]) = {
import util.control.Exception.allCatch
var iter = getIter()
def f: T = allCatch.opt(iter.next).getOrElse{iter = getIter(); f}
Iterator.continually { f }
}

关于exception - 在 Scala 中出现异常时重启迭代器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4010285/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com