컨텍스트 바운드

컨텍스트 바운드 (Context Bounds)

많은 상황에서 컨텍스트 파라미터의 이름은 굳이 직접 언급하지 않아도 돼요. 그 이름이 다른 컨텍스트 파라미터를 위한 합성 인자(synthesized argument)에 컴파일러가 사용할 뿐, 우리 코드에서는 쓰일 일이 없거든요. 그럴 때는 파라미터 이름을 아예 정의하지 않고 타입만 적어주면 됩니다.

출처: Scala 3 Book — Context Bounds

배경

컬렉션에서 최댓값을 반환하는 메서드 maxElement를 생각해 볼게요.

// Scala 2
def maxElement[A](as: List[A])(implicit ord: Ord[A]): A =
  as.reduceLeft(max(_, _)(ord))
// Scala 3
def maxElement[A](as: List[A])(using ord: Ord[A]): A =
  as.reduceLeft(max(_, _)(using ord))

maxElement 메서드는 Ord[A] 타입의 컨텍스트 파라미터를 받아서, 그저 max 메서드에 인자로 넘겨주기 위해서만 사용해요.

이해를 돕기 위해 maxOrd의 정의도 함께 볼게요. (실무에서는 List에 이미 있는 max 메서드를 쓰면 되고, 이 예시는 설명을 위해 만들어 낸 거라는 점만 기억해 두세요.)

// Scala 2
/** Defines how to compare values of type `A` */
trait Ord[A] {
  def greaterThan(a1: A, a2: A): Boolean
}

/** Returns the maximum of two values */
def max[A](a1: A, a2: A)(implicit ord: Ord[A]): A =
  if (ord.greaterThan(a1, a2)) a1 else a2
// Scala 3
/** Defines how to compare values of type `A` */
trait Ord[A]:
  def greaterThan(a1: A, a2: A): Boolean

/** Returns the maximum of two values */
def max[A](a1: A, a2: A)(using ord: Ord[A]): A =
  if ord.greaterThan(a1, a2) then a1 else a2

max 메서드도 maxElement처럼 Ord[A] 타입의 컨텍스트 파라미터를 받는 걸 확인할 수 있어요.

컨텍스트 인자 생략하기

max 메서드에서 ord가 컨텍스트 파라미터이므로, maxElement의 구현 안에서 max를 호출할 때 컴파일러가 그 값을 대신 채워 줄 수 있어요.

// Scala 2
def maxElement[A](as: List[A])(implicit ord: Ord[A]): A =
  as.reduceLeft(max(_, _))
// Scala 3
def maxElement[A](as: List[A])(using Ord[A]): A =
  as.reduceLeft(max(_, _))

max에 명시적으로 넘겨줄 필요가 없으니, maxElement 정의에서는 그 이름을 빼버려도 돼요. 이렇게 이름 없는 컨텍스트 파라미터를 익명 컨텍스트 파라미터(anonymous context parameter) 라고 불러요.

컨텍스트 바운드

이런 배경을 바탕으로, 컨텍스트 바운드(context bound) 는 “타입 파라미터에 컨텍스트 파라미터를 적용한 패턴”을 짧게 표현하는 축약 문법이에요.

컨텍스트 바운드를 쓰면 maxElement 메서드를 이렇게 적을 수 있어요.

// Scala 2 and 3
def maxElement[A: Ord](as: List[A]): A =
  as.reduceLeft(max(_, _))

메서드나 클래스의 타입 파라미터 A에 붙은 : Ord 같은 바운드는 Ord[A] 타입의 컨텍스트 파라미터를 의미해요. 내부적으로 컴파일러는 이 문법을 위 배경 섹션에서 본 형태로 변환해 줍니다. 컨텍스트 바운드에 대해 더 알고 싶다면 Scala FAQ의 “컨텍스트 바운드란 무엇인가?” 섹션을 참고하세요.

더 알아보기 (Learn more)