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

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

问题描述

Option monad 是一种很好的表达方式,可以在 Scala 中处理有或无的事情.但是,如果在无事发生"时需要记录一条消息怎么办?根据 Scala API 文档,

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,

Either 类型通常用作替代 scala.Option where Left代表失败(按照惯例)和Right 类似于 Some.

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)

如果知道您如何在代码中使用 Either 和/或关于重构上述代码的更好想法,我将不胜感激.

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

推荐答案

Either 用于返回可能的两个有意义的结果之一,不像 Option 用于返回单个有意义的结果或什么都不返回.

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

下面给出了一个易于理解的示例(不久前在 Scala 邮件列表中流传):

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

顾名思义,如果block"执行成功,就会返回Right()".否则,如果抛出 Throwable,它将返回Left()".使用模式匹配处理结果:

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

希望有所帮助.

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

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