scala - 为什么在 LiftWeb/Scala 中使用 Box/Option 而不是 Exception?

标签 scala lift

所以,我一直在阅读this article关于 LiftWeb 中 Box 的使用,这似乎是官方文档的一部分,因为它通过源代码注释链接。 我的问题是,为什么 Box/Failure 比实际编码时没有 null 并抛出异常更好,该异常将在顶层被捕获并转换为适当的错误代码/消息。所以而不是

case "user" :: "info" :: _ XmlGet _ =>
  for {
    id <- S.param("id") ?~ "id param missing" ~> 401
    u <- User.find(id) ?~ "User not found"
  } yield u.toXml

为什么不

case "user" :: "info" :: _ XmlGet _ => User.find(S.param("id").openOrThrow(
    new IllegalArgumentException("idParamMissing"))).toXml

并且让User.find抛出类似NotFoundException

的东西

最佳答案

假设您有一个方法执行某些可能会失败的操作,例如获取网页。

def getUrl(url: String): NodeSeq = {
   val page = // ...
   // ...
   if (failure) throw new PageNotFoundException()
   page
}

如果你想使用它,你需要这样做

val node = try {
  getUrl(someUrl)
} catch {
  case PageNotFoundException => NodeSeq.Empty
}

或类似的视情况而定。不过,这样做看起来还是可以的。但现在假设您想要对 URL 集合执行此操作。

val urls = Seq(url1, ...)
val nodeseqs: Seq[NodeSeq] = try {
  urls.map(getUrl)
} catch {
  case PageNotFoundException => Seq.Empty
}

好的,只要无法加载其中一页,就会返回一个空序列。如果我们希望收到尽可能多的信息怎么办?

val urls = Seq(url1, ...)
val nodeseqs: Seq[NodeSeq] = urls.map { url =>
  try {
    getUrl(url)
  } catch {
    case PageNotFoundException => NodeSeq.Empty
  }
}

现在我们的逻辑与错误处理代码混合在一起。

将其与以下内容进行比较:

def getUrl(url: String): Box[NodeSeq] = {
  val page = // ...
  // ...
  if (failure) Failure("Not found")
  else Full(page)
}

val urls = Seq(url1, ...)
val nodeseqs: Seq[Box[NodeSeq]] = urls.map(getUrl(url)).filter(_.isDefined)
// or even
val trueNodeseqs: Seq[NodeSeq] = urls.map(getUrl(url)).flatten

使用OptionBox(或Either或scalaz'Validation)让您有更多的决定权何时处理问题比抛出异常更重要。

除了异常(exception)情况,您只能遍历堆栈并将其捕获为那里的某个点。如果您将故障编码在类型中,您可以随身携带它,只要您愿意,并在您认为最合适的情况下处理它。

关于scala - 为什么在 LiftWeb/Scala 中使用 Box/Option 而不是 Exception?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8329311/

相关文章:

scala - 如何使用 Shapeless 创建一个对 arity 进行抽象的函数

scala - 有什么方法可以从Maven构建中的Protobuf文件生成Scala代码?

scala - Scala的Lift如何管理状态?

scala - 如何: Custom Field in Lift-Record-Squeryl

scala - 如何组合两个函数?

scala - 使用 scala 基于对 Spark DataFrame 中现有列的聚合添加新列

Scala - 具有大量字段的域对象

ruby - 为什么要在框架 Web 服务器前面使用 http 服务器?

security - Lift 是否会阻止 HTTP 响应拆分?

scala - 使用 Actor 时将普通方法调用与消息混合在一起?