스칼라에서
“Either is both, and Both is neither.” - Plutarch
Either
는 언어를 처음 배울 때 간과하기 쉬운 scala의 또 다른 모나드 유형입니다. 그러나 Scala와 Scala(및 FP) 관용구에 대한 많은 근거가 결합되어 있으므로 익숙해지는 데 시간을 할애할 가치가 있다고 생각합니다.모나드 유형으로서
Either
의 목적은 계산을 선언적이고 기능적인 스타일로 구성할 수 있도록 하는 것입니다.그러나 둘 중 하나는 무엇입니까?
Either
는 두 가지 유형 중 하나일 수 있는 값의 래퍼 유형입니다. 두 숫자를 나누는 방법을 작성하고 싶다고 가정합니다. 나누기가 성공하면 double을 반환하고 싶습니다. 실패하면 메시지와 함께 문자열을 반환하고 싶습니다.Java에서 우리는 실제로 이것을 할 수 없습니다.
// can't do this
public *what?* method(int num, int denom) {
if (denom == 0) {
return "cannot divide by 0";
} else {
return (double)denom / num;
}
}
우리는 예외를 던질 수 있고, 호출 코드가 그것을 포착하고 무엇을 할지 결정하게 할 수 있습니다.
public double method(int num, int denom) throws IllegalArgumentException {
if (denom == 0) {
throw new IllegalArgumentException("cannot divide by 0");
} else {
return (double)denom / num;
}
}
...
// calling code
try {
double res = method(1, 0);
doSometh(res);
} catch (IllegalArgumentException iae) {
doSomethElse(iae.getMessage());
}
이 예제는 사소하고 원하는 작업이 아니지만 Java 구현 imho에는 여러 가지 문제가 있습니다.
둘 중 하나를 입력
앞에서 언급했듯이
Either
는 두 가지 일반 유형 중 하나를 래핑합니다. 위의 장난감 예제에서는 Either[String, Double]
를 사용할 수 있으며 코드는 다음과 같습니다.def method(num: Int, denom: Int): Either[String, Double] = {
if (denom == 0) Left("cannot divide by 0")
else Right(denom.asDouble / num)
}
...
// calling code
method(1, 0) match {
case Left(s) => // do something stringy with s
case Right(d) => // do something doubley with d
}
이것이 Java 코드의 문제를 훌륭하게 해결한다고 생각합니다. 간결하고 명확합니다. 두 값 유형은 의미상 예외가 아닌 다른 경로일 뿐입니다. 사실 String 값을 래핑하기 위해 예외를 사용할 필요가 전혀 없습니다. 그리고 부작용이 없습니다.
더 관련된 예
위의 내용은
Either
의 일부 측면을 캡처하지만 실제 성능은 많은 계산을 실행할 때 발생하며 그 중 하나는 실패할 수 있습니다. 특히 Java 코드가 있는 경우 예외를 발생시키는 상호 운용이 가능해야 합니다. 예외를 던지는 Java 모델은 순수하고 멱등적이며 부작용이 없는 함수의 세계에서는 제대로 작동하지 않습니다. 이는 여러 VM 또는 시스템에 걸쳐 있을 수 있는 Akka Actor 시스템에 들어가면 특히 문제가 됩니다.Either
가 기능적인 방식으로 Java 코드로 작업하는 데 어떻게 도움이 되는지 살펴보겠습니다.예외를 발생시키는 것을 좋아하는 Java 메서드가 있다고 가정합니다.
public int unpredictableJavaMethod(int n) {
if (n % 2 == 0) {
return n;
} else {
throw new RuntimeException("failed");
}
}
그리고 이 코드를 실행하고 결과를 평가하는 데 필요한 일련의 값이 있다고 가정합니다.
val results = (1 to 10)
.map(unpredictableJavaMethod)
불행하게도 이것은 값 2에 대한 런타임 예외로 인해 실패할 것이며 나머지 결과에 도달하지 못할 것입니다. 오히려 다행스럽게도 계산을 다음과 같이 래핑할 수 있습니다.
def throwableToLeft[T](block: => T): Either[java.lang.Throwable, T] =
try {
Right(block)
} catch {
case ex => Left(ex)
}
이제 우리는 자바 호출을 래핑하고 다음과 같은 구성 가능한 작업으로 끝낼 수 있습니다.
val results = (1 to 10)
.map(n => throwableToLeft(js.unpredictableJavaMethod(n)))
results.map {
case Left(ex) => // do something with exception
case Right(value) => value
}
맵 대신 결과를 단일 값으로 줄여야 하는 경우 결과를 접을 수 있습니다. 또는 해당 구문이 더 쉬운 경우 이해를 위해 필터링하거나 Scala를 사용하십시오.
합산
따라서 Each는 두 가지 유형을 하나로 결합하는 방법이지만 진정한 힘은 안전하고 기능적인 방식으로 Java 코드를 Scala 프로젝트에 통합하는 것을 지원하는 방식에 있습니다.
Reference
이 문제에 관하여(스칼라에서), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/stefintrim/either-in-scala-25jf텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)