【问题标题】:Why Scala's Try has no type parameter for exception type?为什么 Scala 的 Try 没有异常类型的类型参数?
【发布时间】:2014-12-30 15:50:10
【问题描述】:

我很好奇为什么scala.util.Try 没有像这样的异常类型的类型参数

abstract class Try[+E <: Throwable, +T] {
  recoverWith[U >: T](f: PartialFunction[E, Try[E, U]]): Try[E, U]
  ...
}

对文档有帮助,例如

def parseInt(s: String): Try[NumberFormatException, Int]

仍然无法表达像throws SecurityException, IllegalArgumentException 这样的不相交的异常类型,但至少朝这个方向迈出了一步。

【问题讨论】:

  • 您的目标是让Try { foo } 只捕获来自foo 的特定异常,而不是所有异常?
  • 我的目标是表明返回 Try 的函数只能在特定异常下失败,而不是任何 Throwable
  • 我的回答有什么相关性吗?
  • 是的,我给了它+1。我主要好奇的不是如何克服它,而是为什么它一开始就不存在。就像在这种情况下会被破坏一样。
  • 在这方面尝试似乎并不完美,是的。

标签: scala exception-handling try-catch algebraic-data-types


【解决方案1】:

这可能是您正在寻找的:

import scala.util.control.Exception._
import scala.util.{ Success, Failure }

def foo(x: Int): Int = x match {
  case 0 => 3
  case 1 => throw new NumberFormatException
  case _ => throw new NullPointerException
}

val Success(3) = catching(classOf[NumberFormatException]).withTry(foo(0))
val Failure(_: NumberFormatException) = catching(classOf[NumberFormatException]).withTry(foo(1))
// val neverReturns = catching(classOf[NumberFormatException]).withTry(foo(2))

scala.util.control.Exception$


但是,没有办法将 Try[T] 专门化为假设的 Try[ExcType, T] 之类的东西;为了让它工作,你需要像Either这样的东西(但可能更复杂的东西,比如scalaz.\/,或者,对于超过1个异常类,Shapeless'Coproduct):

def bar(x: Int): Either[NumberFormatException, Int] = {
  catching(classOf[NumberFormatException]).withTry(foo(x)) match {
    case Success(x) => Right(x)
    case Failure(exc) => Left(exc.asInstanceOf[NumberFormatException])
  }
}

println(bar(0)) // Right(3)
println(bar(1)) // Left(java.lang.NumberFormatException)
// println(bar(2)) // throws NullPointerException

应该可以将其概括为适用于任意数量异常类型的通用助手。在这种情况下,您肯定必须使用 Shapeless 的 Coproductfacilities for abstracting over arity。不幸的是,这是一个重要的练习,我现在没有时间为你实施。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-02-04
    • 1970-01-01
    • 2012-02-12
    • 2012-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多