【问题标题】:more readable scala pattern for matching success用于匹配成功的更具可读性的 scala 模式
【发布时间】:2014-10-14 03:25:42
【问题描述】:

我发现成功案例经常隐藏在许多错误和一个成功的匹配中。是否有另一种方法可以更清晰地编写此代码,以使成功可能通过在部分函数中包含所有错误而脱颖而出?或者,也许还有另一种写法,但更简洁。一般来说,我只是在寻找可以完成的其他想法/解决方案。

results.responseCode match {
  case Success =>
    // TODO make this less smelly. can results.results be None?
    val searchResults = results.results.get.results
    SomeService.getUsersFromThriftResults(
      userRepo,
      searchResults,
      Seq(WithCounts)) map { userResults =>
      val renderableStatuses = getStatuses(searchResults, userResults.userMap)
      new JsonAction(transformedQuery, renderableStatuses)
    }
  case ErrorInvalidQuery =>
    throw new SomeBadRequestException("invalid query")
  case ErrorOverCapacity |
       ErrorTimeout =>
    throw new SomeServiceUnavailableException("service unavailable")
  //TODO: take care of these errors differently
  //          case ErrorInvalidWorkflow |
  //               ErrorBackendFailure |
  //               ErrorEventNotFound |
  //               PartialSuccess |
  case _ =>
    throw new SomeApplicationException("internal server error")
}

【问题讨论】:

  • 我不明白为什么平面版已经不是非常好和简单了。

标签: scala scala-2.9


【解决方案1】:

您可以使用orElse 链接部分函数。

类似

type ResponseCode = Int // This would be the type of the results.responseCode.
type RespHandler = PartialFunction[ResponseCode, JsonAction]

val invalidQuery: RespHandler =
  { case ErrorInvalidQuery => ... }

val overCapacity: RespHandler =
  { case ErrorOverCapacity => ... }

results.responseCode match {
  case Success => ...
} orElse invalidQuery orElse overCapacity orElse ...

您可以在这篇博文中了解更多信息:Chaining Partial Functions with orElse

编辑:这不像写的那样工作,你需要编写处理然后apply它(例如(success orElse invalidQuery ..)(results.getResponseCode))。

更好的解决方案是将其更改为返回 Try[ResponseCode] 并在 Failure 匹配块中处理异常。

【讨论】:

  • 如果您能够更改 API,您仍应使用 Try 或类似名称。
  • 这是错误的。匹配的 case 块不是 PF,尽管它看起来像一个。我猜没有人在 REPL 中输入这个?确实,您可以将 PF 链接为 (a orElse b)(x)
  • SO 需要一个必须运行 sn-ps 的功能;或者你可以注释sn-p应该被验证;也许 OP 只能请求经过验证的 sn-ps。
  • 你说得对,这行不通。我在 catch 看到了它,并认为你可以对 match 做同样的事情。
【解决方案2】:

你可以试试Try[A]

文档中的示例:

import scala.util.{Try, Success, Failure}

def divide: Try[Int] = {
  val dividend = Try(Console.readLine("Enter an Int that you'd like to divide:\n").toInt)
  val divisor = Try(Console.readLine("Enter an Int that you'd like to divide by:\n").toInt)
  val problem = dividend.flatMap(x => divisor.map(y => x/y))
  problem match {
    case Success(v) =>
      println("Result of " + dividend.get + "/"+ divisor.get +" is: " + v)
      Success(v)
    case Failure(e) =>
      println("You must've divided by zero or entered something that's not an Int. Try again!")
      println("Info from the exception: " + e.getMessage)
      divide
  }
}

【讨论】:

    【解决方案3】:

    您应该考虑使用 Either[Throwable, A] 来表示结果类型。

    http://tersesystems.com/2012/12/27/error-handling-in-scala/

    【讨论】:

      【解决方案4】:

      您可以将结果转换为Either[ResponseCode, Content]

      def codeToEither(result: Result): Either[ResponseCode, Content] = 
        result.responseCode match {
          case Success => Right(result.results.get.results)
          case _       => Left(result.responseCode)
        }
      

      然后fold 结束它

      codeToEither(result).fold(
        errorCode => ... ,
        content   => ...
      )
      

      如果您愿意,也可以以同样的方式将结果转换为Either[Exception, Content]

      【讨论】:

      • net.databinder.dispatch 库提供了一个可以为您提供 Either 的接口。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-03-26
      • 2023-03-12
      • 1970-01-01
      • 2016-05-16
      • 1970-01-01
      • 1970-01-01
      • 2019-10-02
      相关资源
      最近更新 更多