수색…


구성

부분 함수는 종종 부분의 전체 함수를 정의하는 데 사용됩니다.

sealed trait SuperType
case object A extends SuperType
case object B extends SuperType
case object C extends SuperType

val pfA: PartialFunction[SuperType, Int] = {
  case A => 5
}

val pfB: PartialFunction[SuperType, Int] = {
  case B => 10
}

val input: Seq[SuperType] = Seq(A, B, C)

input.map(pfA orElse pfB orElse {
  case _ => 15
}) // Seq(5, 10, 15)

이 용도에서는 부분 함수가 orElse 메서드와 연결된 순서로 시도됩니다. 일반적으로 나머지 부분의 모든 경우와 일치하는 마지막 부분 함수가 제공됩니다. 집합 적으로, 이들 기능의 결합은 전체 기능으로 작용합니다.

이 패턴은 일반적으로 기능이 서로 다른 코드 경로의 디스패처를 효과적으로 작동시킬 수있는 우려를 분리하는 데 사용됩니다. 이는 Akka Actor수신 방법과 같이 일반적입니다.

`collect`와 함께 사용

부분 함수는 전체 함수에 대한 편리한 구문으로 사용되는 경우가 많지만 마지막 와일드 카드 일치 ( case _ )를 포함하여 일부 함수에서는 부분 함수가 중요합니다. 관용적 인 스칼라에서 가장 일반적인 예는 스칼라 컬렉션 라이브러리에 정의 된 collect 메서드입니다. 여기서 부분 함수를 사용하면 컬렉션의 요소를 검사하여 하나의 압축 구문으로 매핑 및 / 또는 필터링하는 일반적인 기능을 사용할 수 있습니다.

예제 1

부분 함수로 정의 된 제곱근 함수가 있다고 가정합니다.

val sqRoot:PartialFunction[Double,Double] = { case n if n > 0 => math.sqrt(n) }

우리는 collect combinator로 호출 할 수 있습니다 :

List(-1.1,2.2,3.3,0).collect(sqRoot)

효과적으로 다음과 같은 작업을 수행합니다.

List(-1.1,2.2,3.3,0).filter(sqRoot.isDefinedAt).map(sqRoot)

예제 2

sealed trait SuperType // `sealed` modifier allows inheritance within current build-unit only
case class A(value: Int) extends SuperType
case class B(text: String) extends SuperType
case object C extends SuperType

val input: Seq[SuperType] = Seq(A(5), B("hello"), C, A(25), B(""))

input.collect {
  case A(value) if value < 10   => value.toString
  case B(text) if text.nonEmpty => text
} // Seq("5", "hello")

위의 예에서주의해야 할 몇 가지 사항이 있습니다.

  • 각 패턴 일치의 왼쪽은 처리 할 요소를 효과적으로 선택하여 출력에 포함시킵니다. 일치하는 case 가없는 값은 단순히 생략됩니다.
  • 오른쪽은 적용 할 사례 별 처리를 정의합니다.
  • 패턴 일치는 가드 문 ( if 절)과 오른쪽에서 사용할 변수를 바인딩합니다.

기본 구문

스칼라는 partial 함수라고 불리는 특별한 함수 를 가지고 있는데, 이는 일반적인 함수 를 확장한다. Function1 이 예상되는 곳이면 PartialFunction 인스턴스를 사용할 수있다. 패턴 매칭 에서도 사용되는 case 구문을 사용하여 부분 함수를 익명으로 정의 할 수 있습니다.

val pf: PartialFunction[Boolean, Int] = {
  case true => 7
}

pf.isDefinedAt(true) // returns true
pf(true) // returns 7

pf.isDefinedAt(false) // returns false
pf(false) // throws scala.MatchError: false (of class java.lang.Boolean)

예제에서 볼 수 있듯이 부분 함수는 첫 번째 매개 변수의 전체 도메인에 정의 할 필요는 없습니다. 표준 Function1 인스턴스는 가능한 모든 모든 인수에 대해 정의된다는 것을 의미하는 total 이라고 가정합니다.

총 기능으로 사용

부분 함수는 관용적 인 스칼라에서 매우 일반적입니다. 이들은 종종 특성에 대한 총 기능을 정의하기 위해 편리한 case 기반 구문에 사용됩니다.

sealed trait SuperType // `sealed` modifier allows inheritance within current build-unit only
case object A extends SuperType
case object B extends SuperType
case object C extends SuperType

val input: Seq[SuperType] = Seq(A, B, C)

input.map {
  case A => 5
  case _ => 10
} // Seq(5, 10, 10)

이렇게하면 일반 익명 함수에서 match 문의 추가 구문을 저장합니다. 비교:

input.map { item => 
  item match {
    case A => 5
    case _ => 10
  }
} // Seq(5, 10, 10)

또한 튜플이나 case 클래스가 함수에 전달 될 때 패턴 매칭을 사용하여 매개 변수 분해를 수행하는 데 자주 사용됩니다.

val input = Seq("A" -> 1, "B" -> 2, "C" -> 3)

input.map { case (a, i) =>
   a + i.toString
} // Seq("A1", "B2", "C3")

지도 함수에서 튜플을 추출하는 용도

이 세 가지 맵 기능은 동일하므로 팀이 가장 쉽게 읽을 수있는 변형을 사용하십시오.

val numberNames = Map(1 -> "One", 2 -> "Two", 3 -> "Three")

// 1. No extraction
numberNames.map(it => s"${it._1} is written ${it._2}" )

// 2. Extraction within a normal function
numberNames.map(it => {
    val (number, name) = it
    s"$number is written $name"
})

// 3. Extraction via a partial function (note the brackets in the parentheses)
numberNames.map({ case (number, name) => s"$number is written $name" })

부분 함수 는 모든 입력과 일치해야합니다. 일치 하지 않는 경우는 런타임에 예외를 throw합니다.



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow