Scala Option返回Unit的函数的一些/无惯用语

时间:2014-11-14 20:12:09

标签: scala exception-handling error-handling

我有许多操作资源的函数对,例如:

def loadFile(name: String): Option[String]
def writeFile(name: String, data: String): ???
当前实现了

loadFile 以使用Option Some / None返回结果String但是 writeFile 呢?

loadFile 一样,如果 writeFile 失败,我希望它返回包含在一个不错的Try或Option中的响应,而不是抛出异常或返回null,Boolean,或响应代码。

有哪些推荐的最佳做法?

def writeFile(name: String, data: String): Try(Unit)

def writeFile(name: String, data: String): Option(Unit)

只是测试成功标志?

最好的scala-thonic方法是什么?

3 个答案:

答案 0 :(得分:4)

这里的其他答案与Try[Unit]几乎相同,但需要更多的样板。这很简单(字面意思是在函数定义中添加3个字母):

def writeFile(name: String, data: String): Try[Unit] = Try {
    // do write operation that may throw an exception
}

Try的巨大优势在于它是一个monad,因此您可以mapflatMap(以及其他内容)组成多个Try {1}}轻松地成为一个人。假设您需要同时执行其中的3个操作,并返回Unit或第一个Exception

val result: Try[Unit] = for {
    a <- writeFile(name1, data1)
    b <- writeFile(name2, data2)
    c <- writeFile(name3, data3)
} yield ()

您可以匹配结果:

result match {
    case Success(_) => println("Success!")
    case Failure(t) => println(s"Failure! {t.getMessage}")
}

您还有一些其他强大的组合函数,如API docs中所示。

您还可以编写更通用的方法来重试失败,如this post中的最后一段代码所示。

答案 1 :(得分:1)

过去,我采用了一种看起来像这样的方法。

trait Result
case object Success extends Result
case class Error(errorReason: String) extends Result

def writeFile(name: String): Result

它与模式匹配范例非常适用。

def writeFileWithRetry(name: String)(numRetries: Int = 2): Result = {
  writeFile(name) match {
    case e: Error => 
      LOG.errorLog(s"Could not write $name: ${e.errorReason}")
      if (numRetries <= 0) e else writeFileWithRetry(name)(numRetries - 1)
    case r => r
  }
}

答案 2 :(得分:0)

   def writeFile(name: String, data: String): Either[Exception, Unit] = try {
      doWrite(name, data)  
      Right(()) 
   } catch {
     case ex => Left(ex)
   }

    writeFile("foo", "bar") match {
       case Left(ex) => println("Failed with exception: " + ex)
       case _ => println("Success!")
    }