【问题标题】:Why Box/Option instead of Exception in LiftWeb/Scala?为什么在 LiftWeb/Scala 中使用 Box/Option 而不是 Exception?
【发布时间】:2011-11-30 16:25:37
【问题描述】:

所以,我一直在阅读 this article 关于 LiftWeb 中 Box 的使用,这似乎是官方文档的一部分,因为它通过源代码 cmets 链接。 我的问题是,为什么 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 的东西

【问题讨论】:

  • 好问题。我从来没想过……
  • @drozzy 确保您还阅读了邮件列表中的答案:goo.gl/5Lv7V

标签: scala option lift


【解决方案1】:

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

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)比抛出异常更能决定何时处理问题。

除了异常,您只能遍历堆栈并将其作为某个点捕获。如果你将失败编码到一个类型中,你可以随身携带,只要你喜欢,在你认为最合适的情况下处理它。

【讨论】:

  • 每个人都在不断给我一个答案,这可以追溯到您所描述的这种情况。虽然在实践中,编写 API 时很少发生。
【解决方案2】:

如果你抛出一个异常,你唯一能做的就是捕捉它。因此,如果页面的两个部分抛出异常,您将永远无法到达第二个部分。如果页面的一部分返回Box,恰好是Failure,而第二部分不需要第一部分的返回值,则两者都可以看到。更一般地说,Box 有一个有用的 API,而 Exception 缺乏。

【讨论】:

  • 是的,这似乎是原因之一。虽然我宁愿考虑一次失败必须阻止你的情况。 David Pollak 在他们的邮件列表中得到了很好的答复:goo.gl/5Lv7V
猜你喜欢
  • 2021-07-05
  • 2011-09-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多