문제

Option 사은 표현 방법은 뭔가 거래 또는 없는 것입니다.하지만 만약 하나의 메시지를 기록할 때""아무것도 발생합니다?에 따라 밀라노 API 설명서

하나 형식으로 자주 사용 대체하는 스칼라.옵션 왼쪽 실패를 나타내(기회)및 오른쪽에 가깝다.

그러나 나는 행운을 찾 모범 사례 사용하거나 또는 좋은 실제 사례를 포함하거나 처리를 위해 실패입니다.마지막으로 왔어요 다음과 같은 코드에 대한 나의 자신의 프로젝트:

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

(참고로 이것은 조각을 실제 프로젝트지 않을 것이다,그래서 컴파일에서 자신의)

나는 감사하는 방법을 알고 당신이 사용하는 Either 에서 당신의 코드 및/또는 더 좋은 아이디어에 refactoring 위의 코드입니다.

도움이 되었습니까?

해결책

둘 중 하나는 단일 의미있는 결과를 반환하는 데 사용되는 옵션과 달리 가능한 두 가지 의미있는 결과 중 하나를 반환하는 데 사용됩니다.

이해하기 쉬운 예는 아래에 나와 있습니다 (잠시 스칼라 메일 링리스트에 순환) :

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

함수 이름에서 알 수 있듯이 "블록"실행이 성공하면 오른쪽으로 돌아갑니다.u003Cresult> ) ". 그렇지 않으면 던질 수있는 사람이 던져지면 왼쪽 (왼쪽) (u003Cthrowable> ) ". 패턴 매칭을 사용하여 결과를 처리하십시오.

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

도움이되기를 바랍니다.

다른 팁

Scalaz Library에는 유효성 검사라는 이름이 있습니다. "유효한 결과를 얻거나 실패를 얻는 것"으로 사용하는 것보다 관용적입니다.

검증은 또한 오류를 축적 할 수 있습니다.

편집 : "alkike"는 적용 기능이기 때문에 완전하게 거짓입니다. / ( "Disjonction"또는 "One"으로 발음)는 Monad입니다. 검증이 오류를 축적 할 수 있다는 사실은 그 특성 때문입니다. 다른 한편으로, /는 "초기에 멈춘다"자연을 가지고 있으며, 첫 번째 - / ( "왼쪽"또는 "오류")에서 멈춘다. 여기에는 완벽한 설명이 있습니다. http://typelevel.org/blog/2014/02/21/error handling.html

보다: http://scalaz.googlecode.com/svn/continuous/latest/browse.sxr/scalaz/example/examplevalidation.scala.html

주석에 의해 요청 된대로 위의 링크의 복사/붙여 넣기 (일부 줄이 제거됨) :

// Extracting success or failure values
val s: Validation[String, Int] = 1.success
val f: Validation[String, Int] = "error".fail

// It is recommended to use fold rather than pattern matching:
val result: String = s.fold(e => "got error: " + e, s => "got success: " + s.toString)

s match {
  case Success(a) => "success"
  case Failure(e) => "fail"
}

// Validation is a Monad, and can be used in for comprehensions.
val k1 = for {
  i <- s
  j <- s
} yield i + j
k1.toOption assert_≟ Some(2)

// The first failing sub-computation fails the entire computation.
val k2 = for {
  i <- f
  j <- f
} yield i + j
k2.fail.toOption assert_≟ Some("error")

// Validation is also an Applicative Functor, if the type of the error side of the validation is a Semigroup.
// A number of computations are tried. If the all success, a function can combine them into a Success. If any
// of them fails, the individual errors are accumulated.

// Use the NonEmptyList semigroup to accumulate errors using the Validation Applicative Functor.
val k4 = (fNel <**> fNel){ _ + _ }
k4.fail.toOption assert_≟ some(nel1("error", "error"))

코드 조각을 게시하는 것은 매우 고안된다.중 하나를 사용하는 상황에서:

  1. 그것만으로는 충분하지 않습 알고있는 데이터 사용할 수 없습니다.
  2. 당신은 반환해야 하나의 두 가지 종류가 있습니다.

돌에는 예외로 왼쪽은,참으로,일반적으로 사용한 경우.해 시도를 통해/를 잡을,그것은 이점을 유지하는 코드는,함께 만드는 경우는 예외입니다 예상 결과.가장 일반적인 방법으로 처리하거나는 패턴 매칭:

result match {
  case Right(res) => ...
  case Left(res) => ...
}

또 다른 흥미로운 방법을 처리 Either 이 나타나면에서 컬렉션입니다.을 수행할 때 지도 컬렉션을 던지고,예외가 되지 않을 수도 있습한,그리고 당신은 반환 할 수 있는 몇 가지 정보를 다른다"가".를 사용하거나 그렇게 할 수 있습 느끼지 없이 알고리즘:

val list = (
  library 
  \\ "books" 
  map (book => 
    if (book \ "author" isEmpty) 
      Left(book) 
    else 
      Right((book \ "author" toList) map (_ text))
  )
)

여기서 우리는 우리의 목록을 얻을 모든 저자로서 라이브러리 목록이 없이 책의 저자이다.그래서 우리는 더 적절하게 처리하는:

val authorCount = (
  (Map[String,Int]() /: (list filter (_ isRight) map (_.right.get))) 
   ((map, author) => map + (author -> (map.getOrElse(author, 0) + 1)))
  toList
)
val problemBooks = list flatMap (_.left.toSeq) // thanks to Azarov for this variation

그래서,기본거나 사용이 간다.그것은 특히 유용한 클래스만 경우에 당신은 그것을 볼 수 있다.다른 한편으로,그것은 쓸모없다.

고양이는 예외적으로 던지는 코드에서 중 하나를 만들 수있는 좋은 방법이 있습니다.

val either: Either[NumberFormatException, Int] =
  Either.catchOnly[NumberFormatException]("abc".toInt)
// either: Either[NumberFormatException,Int] = Left(java.lang.NumberFormatException: For input string: "abc")

안에 https://typelevel.org/cats/datatypes/either.html#working-with-exception-y-code

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top