使用Either在Scala代码中处理故障 [英] Using Either to process failures in Scala code

查看:117
本文介绍了使用Either在Scala代码中处理故障的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

选项 monad是处理Scala中的某些或某些事物的绝妙表达方式。但是如果在什么都没有的情况下需要记录消息呢?根据Scala API文档,


这两种类型通常用作scala的
替代方案。其中Left
表示失败(按惯例)和
右表示与Some类似。


然而,我没有找到运气使用Either的最佳实践或涉及Either的良好实际示例来处理失败。最后,我为自己的项目提出了以下代码:

  def logs:Array [String] = {
def props:Option [Map [String,Any]] = configAdmin.map {ca =>
val config = ca.getConfiguration(PID,null)
config.properties getOrElse immutable.Map.empty
}
def checkType(any:Any):Option [Array [String ]] =任何匹配{
case a:Array [String] =>一些(a)
案例_ => None
}
def lookup:对于{val属性< - props.toRight('warning - >ConfigurationAdmin服务)[[Symbol,String],Array [String]] =
)$ right $ b $ val logsParam < - properties.get(logs)。toRight('debug - >'logs'not defined in the configuration)。right
val array < - checkType(logsParam).toRight('warning - >未知类型的'logs'配置参数)。right}
产量数组

lookup.fold(failure => ; {失败匹配{
case('warning,msg)=> log(LogService.DEBUG,msg)$(logService.WARNING,msg)
case('debug,msg)=& b $ b case _ =>
}; new Array [String](0)},success =>成功)
}

(请注意,这是一个真实项目的片段,因此它不会自行编译)



我很感激知道你如何在你的代码中使用或者和/或重构上述代码的更好的想法。

解决方案



一个简单的方法用于返回可能的两个有意义的结果中的一个,与用于返回单个有意义结果的Option不同。理解例子如下(在Scala邮件列表中发布一段时间):

$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $' => T):[java.lang.Throwable,T] =
try {
Right(block)
} catch {
case ex =>左(前)
}

如函数名所示,如果执行block 是成功的,它将返回右(< result>)。否则,如果抛出一个Throwable,它将返回Left(< throwable>)。使用模式匹配处理结果:

  var s =hello
throwableToLeft {s.toUpperCase} match {
case Right(s)=> println(s)
case Left(e)=> e.printStackTrace
}
//打印HELLO
$ bs = null
throwableToLeft {s.toUpperCase} match {
case Right(s)= > println(s)
case Left(e)=> e.printStackTrace

//打印NullPointerException堆栈跟踪


Option monad is a great expressive way to deal with something-or-nothing things in Scala. But what if one needs to log a message when "nothing" occurs? According to the Scala API documentation,

The Either type is often used as an alternative to scala.Option where Left represents failure (by convention) and Right is akin to Some.

However, I had no luck to find best practices using Either or good real-world examples involving Either for processing failures. Finally I've come up with the following code for my own project:

    def logs: Array[String] = {
        def props: Option[Map[String, Any]] = configAdmin.map{ ca =>
            val config = ca.getConfiguration(PID, null)
            config.properties getOrElse immutable.Map.empty
        }
        def checkType(any: Any): Option[Array[String]] = any match {
            case a: Array[String] => Some(a)
            case _ => None
        }
        def lookup: Either[(Symbol, String), Array[String]] =
            for {val properties <- props.toRight('warning -> "ConfigurationAdmin service not bound").right
                 val logsParam <- properties.get("logs").toRight('debug -> "'logs' not defined in the configuration").right
                 val array <- checkType(logsParam).toRight('warning -> "unknown type of 'logs' confguration parameter").right}
            yield array

        lookup.fold(failure => { failure match {
            case ('warning, msg) => log(LogService.WARNING, msg)
            case ('debug, msg) =>   log(LogService.DEBUG, msg)
            case _ =>
        }; new Array[String](0) }, success => success)
    }

(Please note this is a snippet from a real project, so it will not compile on its own)

I'd be grateful to know how you are using Either in your code and/or better ideas on refactoring the above code.

解决方案

Either is used to return one of possible two meaningful results, unlike Option which is used to return a single meaningful result or nothing.

An easy to understand example is given below (circulated on the Scala mailing list a while back):

def throwableToLeft[T](block: => T): Either[java.lang.Throwable, T] =
  try {
    Right(block)
  } catch {
    case ex => Left(ex)
  }

As the function name implies, if the execution of "block" is successful, it will return "Right(<result>)". Otherwise, if a Throwable is thrown, it will return "Left(<throwable>)". Use pattern matching to process the result:

var s = "hello"
throwableToLeft { s.toUpperCase } match {
  case Right(s) => println(s)
  case Left(e) => e.printStackTrace
}
// prints "HELLO"

s = null
throwableToLeft { s.toUpperCase } match {
  case Right(s) => println(s)
  case Left(e) => e.printStackTrace
}
// prints NullPointerException stack trace

Hope that helps.

这篇关于使用Either在Scala代码中处理故障的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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