更具可读性的scala模式,用于匹配成功

时间:2014-08-20 16:53:33

标签: scala scala-2.9

我发现成功案例经常被埋没在许多错误和一次成功的匹配中。有没有另一种方法可以更清晰地写出来,以便成功突出或许通过在部分函数中包含所有错误?或许,还有另一种方式来编写它,但只是更清洁。我一般只是在寻找可以做到的其他想法/解决方案。

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")
}

4 个答案:

答案 0 :(得分:3)

您可以使用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匹配块中处理异常。

答案 1 :(得分: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
  }
}

答案 2 :(得分:1)

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

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

答案 3 :(得分:1)

您可以将结果转换为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]

相关问题