shj*_*shj 16 dictionary loops scala exception scala-collections
在Scala中循环迭代时处理异常的最佳方法是什么?例如,如果我有一个可以抛出异常的convert()方法,我想捕获该异常,记录它并继续迭代.是否有"scala"方式来做到这一点?
理想情况下,我喜欢......
val points: Seq[Point] = ...
val convertedPoints: Seq[ConvertedPoint] = points.map(
p => {
try { p.convert() }
catch { case ex: Exception => logger.error("Could not convert", ex) }
})
Run Code Online (Sandbox Code Playgroud)
你不能做上面的代码,因为它不是从一个列表到另一个列表的直接映射(你得到Seq [Any]而不是Seq [ConvertedPoint]).任何帮助将不胜感激!
谢谢!
Dan*_*ral 17
有趣的是我在解释使用scala.util.control.Exceptionover try/ 的优点时遇到了很多麻烦catch,然后我开始看到问题,这些问题可以从中得到完美的例子.
这里:
import scala.util.control.Exception._
List(1, 23, 5, 2, 0, 3, 2) flatMap (x => catching(classOf[Exception]) opt (10 / x))
Run Code Online (Sandbox Code Playgroud)
您自己的代码如下所示:
val points: Seq[Point] = ...
val convertedPoints: Seq[ConvertedPoint] = points.flatMap(
p => handling(classOf[Exception]) by { ex =>
logger.error("Could not convert", ex); None
} apply Some(p.convert)
)
Run Code Online (Sandbox Code Playgroud)
或者,如果你重构它:
val exceptionLogger = handling(classOf[Exception]) by { ex =>
logger.error("Could not convert", ex); None
}
val convertedPoints: Seq[ConvertedPoint] = points.flatMap(p => exceptionLogger(Some(p.convert)))
Run Code Online (Sandbox Code Playgroud)
DaG*_*RRz 16
flatMap可能就是你要找的东西,但map函数有记录副作用,如果点是视图,这些副作用可能不会立即发生:
val convertedPoints = points.view.flatMap { p =>
try {
Some(p.convert)
} catch {
case e : Exception =>
// Log error
None
}
}
println("Conversion complete")
println(convertedPoints.size + " were converted correctly")
Run Code Online (Sandbox Code Playgroud)
这将打印:
Conversion complete
[Error messages]
x were converted correctly
Run Code Online (Sandbox Code Playgroud)
在你的情况下,删除视图,你可能没事.:)
要使转换成为纯函数(无副作用),您可能会使用Either.虽然我不认为这是值得的(除非你真的想对错误做些什么),这里有一个非常完整的例子:
case class Point(x: Double, y: Double) {
def convert = {
if (x == 1.0) throw new ConversionException(this, "x is 1.0. BAD!")
else ConvertedPoint(x, y)
}
}
case class ConvertedPoint(x: Double, y: Double)
class ConversionException(p: Point, msg: String) extends Exception(msg: String)
val points = List(Point(0,0), Point(1, 0), Point(2,0))
val results = points.map { p =>
try {
Left(p.convert)
} catch {
case e : ConversionException => Right(e)
}
}
val (convertedPoints, errors) = results.partition { _.isLeft }
println("Converted points: " + convertedPoints.map(_.left.get).mkString(","))
println("Failed points: " + errors.map( _.right.get).mkString(","))
Run Code Online (Sandbox Code Playgroud)
小智 6
也许你想要一个flatMap.这是一个例子,应该看看它是如何适合的:-)
List(1,2,3,4).flatMap(x => if (x > 2) Some(x) else None)
Run Code Online (Sandbox Code Playgroud)
以上将使用副作用记录(打印或放入可变的东西 - 如果这样做,请确保强制评估!).为了解决副作用和警告,映射函数可能只是Point -> Either[CovertedPoint,Exception],然后结果可以用Seq.partition或类似地分开.
| 归档时间: |
|
| 查看次数: |
9760 次 |
| 最近记录: |