I'm writing a Scala app using some 3rd party library. When iterating over a collection from that library an exception occurs, which I want to ignore, and go on with the iteration. The whole thing is inside a for loop with yield.
val myFuntionalSequence = for {
mailing <- mailingCollection
} yield (mailing.getName, mailing.getSubject)
As said, the error occurs inside the iteration, so this line:
mailing <- mailingCollection
If I would put a try catch around the whole loop, then I cannot continue with the iteration. I have a non-functional solution to have the same output as above, but I want to keep the whole app in a functional style. This is what I came up within a non-functional way:
case class MyElement(name: String, subject: String)
...
var myNonFunctionalList = scala.collection.mutable.ListBuffer[MyElement]()
while(mailingIterator.hasNext) {
try {
val mailing = mailingIterator.next()
myNonFunctionalList += MyElement(mailing.getName, mailing.getSubject)
} catch {
case e: Exception => println("Error")
}
}
My question is, do you know a functional way of trying to iterate through a for loop and on error skipping that element and only returning the elements where the iteration worked?
Thanks, Felix
If you want to remain functional then you need a recursive function to unpick the unreliable iterator.
This is untested code, but it might look like this:
def safeIterate[T](i: Iterator[T]): List[Try[T]] = {
@annotation.tailrec
def loop(res: List[Try[T]]): List[Try[T]] =
if (i.hasNext) {
loop(Try(i.next) +: res)
} else {
res.reverse
}
loop(Nil)
}
You can check each Try value to see which iterations succeeded or failed. It you just want the success values then you can call .flatMap(_.toOption) on the List. Or use this version of safeIterate:
def safeIterate[T](i: Iterator[T]): List[T] = {
@annotation.tailrec
def loop(res: List[T]): List[T] =
if (i.hasNext) {
Try(i.next) match {
case Success(t) => loop(t +: res)
case _ => loop(res)
}
} else {
res.reverse
}
loop(Nil)
}
Someone smarter than me can probably make this return another Iterator rather than a List.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With