Scala의 옵션 이해
이 기사에서는 Scala에서 선택적 데이터 요소를 사용하는 방법을 배웁니다. Scala의 Options
는 강력한 코드를 작성하는 데 도움이 됩니다.
Scala의 Option
유형
스칼라에서 Option[T]
는 주어진 유형의 값을 0개 또는 1개 저장하는 컨테이너
입니다. Scala의 Option
을 사용하여 선택적 값을 관리하면 두 가지를 보장할 수 있습니다.
- 유형 안전성: 선택적 값을 매개변수화할 수 있습니다.
- 기능적 인식:
option
유형은 프로그램에서 더 적은 수의 버그가 생성되도록 하는 많은 기능적 기능을 제공합니다.
스칼라에서 Option[T]
는 Some[T]
또는 None[T]
객체로 표현됩니다. 여기 scala.Option
은 추상적이고 확장된 기본 클래스이므로 Scala의 Option
은 컨테이너처럼 작동합니다.
Option
클래스와 그 하위 클래스에는 구체적인 유형이 필요하다는 것을 기억하십시오. 다음 구문과 같이 명시적이거나 유추될 수 있습니다.
예시:
val obj1: Option[Int] = None
val obj2 = Some(100)
여기서 obj1
과 obj2
는 Option[Int]
의 객체입니다. 한 가지 일반적인 질문은 Option
이 Some
인지 None
인지 확인하는 방법입니다.
이 문제를 해결하기 위해 다음과 같은 기능이 있습니다.
isEmpty
: 이 메서드는 개체가None
인 경우true
를 반환합니다.nonEmpty
: 이 메소드는 객체가Some
이면true
를 반환합니다.isDefined
: 이 메소드는 객체가Some
이면true
를 반환합니다.
Scala에서 Option
의 값 검색
get
메소드를 사용하여 Options
값을 검색할 수 있습니다. get
메소드가 None
객체에 대해 호출되면 NoSuchElementException
이 발생하며 성공 편향
이라고도 합니다.
예제 코드:
val obj1: Option[Int]= ...
val v1 = if (obj1.isDefined)
{
obj1.get
}
else
{
0
}
위의 코드는 패턴 일치를 사용하여 작성할 수도 있습니다.
예제 코드:
val obj1: Option[Int]= ...
val v1 = obj1 match {
case Some(temp) =>
temp
case None =>
0
}
값을 검색하는 getOrElse
및 orElse
와 같은 다른 방법도 있습니다.
getOrElse
: 이 메소드는 객체가Some
인 경우 값을 검색합니다. 그렇지 않으면 기본값을 반환합니다.orElse
: 이 메서드는 개체가Some
인 경우 값을 검색합니다. 그렇지 않으면alternate
옵션을 반환합니다.
선택적 값이 설정되지 않은 경우 getOrElse
메서드는 기본값을 반환할 수 있으므로 매우 유용합니다.
통사론:
val v1 = obj1.getOrElse(0)
Scala의 컨테이너로서의 Option
Option
이 Scala에서 다른 값에 대한 컨테이너임을 보았듯이 List
를 비슷하게 탐색하는 것처럼 Option
을 탐색할 수 있습니다.
이 컨테이너에 대한 몇 가지 메서드를 살펴보겠습니다. Scala의 Option.map
메소드 구문:
final def map[Y](f: (X) => Y): Option[Y]
예제 코드:
val obj1: Option[Int] = Some(100)
assert(obj1.map(_.toString).contains("100"))
assert(obj1.map(_ * 2.0).contains(200))
val obj2: Option[Int] = None
assert(obj2.map(_.toString).isEmpty)
위의 예에서는 Option.map
메소드를 사용하여 포함된 값을 다른 유형으로 변환했습니다. Option.map
방법은 프로그램의 흐름 제어
에 영향을 주기 위해 사용될 수도 있습니다.
예제 코드:
val obj1: Option[Int] = Some(10)
val obj2: Option[Int] = None
def mul(n: Int): Int = n * 2
assert(obj1.map(mul).contains(20))
assert(obj2.map(mul).isEmpty)
여기에서 Option[Int]
의 두 개체를 만들었습니다. 첫 번째 개체는 10
값을 갖고 두 번째 개체는 비어 있습니다. 그런 다음 입력에 2
를 곱하는 mul
메서드를 정의했습니다.
마지막으로 mul
방법을 사용하여 obj1
과 obj2
를 매핑합니다. obj1 매핑은 Some(20)
을 제공하고 obj2 매핑은 None
을 제공합니다.
여기서 관찰해야 할 한 가지는 두 번째 호출인 obj2.map(mul)
에서 mul
메서드가 전혀 호출되지 않는다는 것입니다. 필터링으로 흐름 제어도 할 수 있습니다.
이를 위한 많은 방법이 있습니다.
filter
:Options
값이Some
이고 제공된 함수가true
를 반환하는 경우 이 메서드는Option
을 반환합니다.exists
: 이 메서드는Option
이 설정되고 제공된 함수가true
를 반환하는 경우true
를 반환합니다.forall
:exists
메소드와 동일하게 동작합니다.
이러한 기능을 사용하여 코드를 매우 간결하게 작성할 수 있습니다.
가장 높은 점수를 받은 팀을 찾는 예를 들어보겠습니다.
예제 코드:
def highScoringTeam(playerA: Player, playerB: Player, tournament: Tournament): Option[(Player, Int)] =
{ getTopScore(playerA, tournament).foldRight(getTopScore(playerB, tournament)) {
case (playerAInfo, playerBInfo) => playerBInfo.filter {
case (_, scoreB) => scoreB > playerAInfo._2
}.orElse(Some(playerAInfo))
}
}
위의 코드에서 Options
를 컬렉션으로 사용할 수 있다는 점을 활용했습니다. 유일한 차이점은 Option은 최대 하나의 값을 가질 수 있다는 것입니다.