Scala最优雅的方式来处理选项并从Scala Map中引发异常 [英] Scala most elegant way to handle option and throw exception from Scala Map

查看:41
本文介绍了Scala最优雅的方式来处理选项并从Scala Map中引发异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一张地图,想要:

  • 无需处理Option即可获取值
  • 在没有这样的密钥时记录一条消息.
  • 在不存在密钥时,返回默认值(除了记录消息外)也很不错.这是可选的,因为当代码在此处失败时,就不应继续下去.

我有几种方法

val map: Map[String, Int] // defined as such for simplification

// 1 short but confusing with error handling
def getValue(key: String): Int = {
    map.getOrElse(key, scala.sys.error(s"No key '$key' found"))
}

// in case you don't know scala.sys.error 
package object sys {
 def error(message: String): Nothing = throw new RuntimeException(message)
}


// 2 verbose
def getValue(key: String): Int = {
    try {
      map(key)
    } catch {
      case _: Throwable => scala.sys.error(s"No key '$key' found")
    }
}


// 3 Try and pattern matching
import scala.util.{Failure, Success, Try}

def getValue(key: String): Int = {
    Try(map(key)) match{
      case Success(value) => value
      case Failure(ex) => sys.error(s"No key '$key' found ${ex.getMessage}")
    }
}

欢迎使用其他解决方案.我正在寻找简洁而不神秘的东西.使用标准scala(无需Scalaz,Shapeless ...)

Others solutions are welcomed. I'm looking for conciseness without being cryptic. Using standard scala ( no need for Scalaz, Shapeless ... )

灵感:

推荐答案

引发错误的最优雅方法是您的(1):

map.getOrElse(键,抛出/*一些异常*/)

不应使用2nd和3rd选项:您知道可能发生的实际错误:地图不包含键.因此,将其包装在try(或Try)中是多余的工作.更糟糕的是,它将捕获到其他本来不是的例外.特别是不应捕获的致命异常.

The 2nd and 3rd options should not be used: You know which actual error can happen: the map doesn't contain the key. So wrapping it in a try, or Try, is more work than necessary. And worst, it will catch other exceptions that are not meant to be. In particular Fatal exception that should not be caught.

但是,在Scala中管理异常的最优雅的方法是实际跟踪类型.

But, the real most elegant way to manage exceptions in scala is to actually track them with types.

一种简单的通用方法(但有时也通用)是使用Try.一旦您的代码可能失败,一切都将包裹在Try中,以后的代码将在map和flatMap中调用(您可以使用for-comprehension使其更具可读性)

A simple generic way (but sometime too generic) is to use Try. As soon as your code might fail, everything is wrapped in Try and later code is called in map and flatMap (you can use for-comprehension to make it more readable)

一种更具体的方法是使用scalaz中的Escaler或scalaz中的 \/并显式管理错误的类型,例如 \/(MissingData,String)来创建您的某些 MissingData 类.例如:

A more specific way is to use Either (from scala) or \/ from scalaz and explicit the type of error you are managing, such as \/(MissingData, String) for some MissingData class you've made. Eg:

import scalaz.\/
import scalaz.syntax.either._

sealed trait KnownException
case class MissingData(message: String) extends KnownException

// type alias used for readability
type Result[A] = \/[KnownException, A]

// retrieve a param, or a MissingData instance
def getParam(param: Map[String, Int], key: String): Result[Int] = param.get(key) match {
  case None => MissingData(s"no param for key $key").left
  case Some(v) => v.right
}

// example on how to combine multiple \/
// using for-comprehension
def computeAPlusB(param: Map[String, Int]): Result[Int] = for {
  paramA <- getParam(param, "a")
  paramB <- getParam(param, "b")
} yield paramA + paramB

这篇关于Scala最优雅的方式来处理选项并从Scala Map中引发异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆