파라미터 언튜플링

파라미터 언튜플링 (Parameter Untupling)

짝(pair)들의 리스트에서 각 요소를 풀어서 처리하고 싶을 때, 예전에는 패턴 매칭으로 분해해야만 했어요. Scala 3부터는 함수 값에 튜플로 묶인 파라미터를 자동으로 풀어 넘겨주는 '파라미터 언튜플링'이 지원돼서 훨씬 간결하게 쓸 수 있습니다.

출처: Scala 3 Reference

본문

짝들의 리스트가 있다고 해 볼게요.

val xs: List[(Int, Int)]

xs를 각 짝이 숫자들의 합으로 매핑된 Int 리스트로 바꾸고 싶다고 합시다. 예전에는 패턴 매칭 분해가 최선의 방법이었어요.

xs map {
  case (x, y) => x + y
}

옳은 코드긴 한데 좀 불편하고 헷갈리기도 해요. case가 마치 패턴 매칭이 실패할 수도 있다는 뉘앙스를 주거든요. Scala 3에서는 더 짧고 명확한 대안을 쓸 수 있어요:

xs.map {
  (x, y) => x + y
}

또는 동등하게:

xs.map(_ + _)

그리고:

def combine(i: Int, j: Int) = i + j
xs.map(combine)

일반적인 규칙은 이래요. n > 1 파라미터를 가진 함수 값은, 기대 타입이 그럴 때 ((T_1, ..., T_n)) => U 형태의 함수 타입으로 감싸져요. 그러면 튜플 파라미터가 분해되어 그 요소들이 바로 밑의 함수에 전달됩니다.

좀 더 정확히 말하면, 이 적응(adaptation)은 불일치하는 형식 파라미터 리스트에 적용돼요. 특히 함수 타입 사이의 변환은 아니에요. 그래서 다음은 받아들여지지 않습니다:

val combiner: (Int, Int) => Int = _ + _
xs.map(combiner)     // Type Mismatch

파라미터를 언튜플링하는 대신, 함수 값을 명시적으로 튜플화해 줘야 해요:

xs.map(combiner.tupled)

강하게 권장되진 않지만, 같은 효과를 내도록 사용자 코드에서 암시적 변환을 제공할 수도 있어요:

import scala.language.implicitConversions

transparent inline given `fallback untupling`: Conversion[(Int, Int) => Int, ((Int, Int)) => Int] = _.tupled

xs.map(combiner)

파라미터 언튜플링은 변환이 적용되기 전에 시도되기 때문에, 스코프 안의 변환이 언튜플링을 무너뜨릴 수 없어요.

참고 (Reference)

더 자세한 내용은 다음을 참고하세요:

  • 더 많은 세부 사항 (More details)
  • 이슈 #897 (Issue #897).