오버로드 해석의 변경 사항

오버로드 해석의 변경 사항 (Changes in Overload Resolution)

Scala 3의 오버로드 해석은 Scala 2보다 세 가지 면에서 나아졌어요. 첫째, 첫 번째 인자 목록뿐 아니라 모든 인자 목록을 고려해요. 둘째, 함수 값의 매개변수 타입이 첫 번째 인자 목록에 있더라도 추론할 수 있어요. 셋째, 기본 인자(default argument)가 더 이상 우선순위 결정에 영향을 주지 않아요.

출처: Scala 3 Reference

본문

첫 번째 인자 목록 너머 보기 (Looking Beyond the First Argument List)

오버로드 해석은 이제 오버로드된 대안들의 집합을 고를 때 인자 목록을 고려할 수 있어요. 예를 들어 다음 코드는 Scala 3에서 컴파일되는 반면, Scala 2에서는 모호한 오버로드 오류가 나요.

def f(x: Int)(y: String): Int = 0
def f(x: Int)(y: Int): Int = 0

f(3)("")     // ok

다음 코드도 컴파일돼요.

def g(x: Int)(y: Int)(z: Int): Int = 0
def g(x: Int)(y: Int)(z: String): Int = 0

g(2)(3)(4)     // ok
g(2)(3)("")    // ok

이게 동작하도록 SLS §6.26.3의 오버로드 해석 규칙에 다음을 추가했어요.

함수가 인자 목록을 두 개 이상 받는 상황에서, n >= 1개의 매개변수 목록을 고려했을 때 오버로드 해석이 여러 경쟁 대안을 만들어 내면, 해석을 n + 1개의 인자 목록으로 다시 시도한다.

이 변경은 새 언어 기능인 확장 메서드(extension method)에서 동기가 나왔어요. 추가 인자 블록을 기준으로 오버로드 해석을 해야 할 필요가 생기기 때문이죠.

확장 메서드가 확장 문법으로 사용될 때는 멤버 메서드와 경쟁하지 않는다는 점을 참고하세요. 반대로, 확장 메서드는 보통의 메서드 호출 문법으로도 호출할 수 있기 때문에, 모호한 경우에는 멤버 메서드가 선호돼요.

함수 값의 매개변수 타입 (Parameter Types of Function Values)

매개변수 타입이 빠진 함수 값의 처리가 개선됐어요. 이제 이런 값을 오버로드된 적용의 첫 번째 인자 목록에 넘길 수 있어요. 단, 나머지 매개변수들이 오버로드된 함수의 변형을 고르기에 충분해야 하죠. 예를 들어 다음 코드는 Scala 3에서 컴파일되는 반면, Scala 2에서는 매개변수 타입 누락 오류가 나요.

def f(x: Int, f2: Int => Int) = f2(x)
def f(x: String, f2: String => String) = f2(x)
f("a", _.toUpperCase)
f(2, _ * 2)

이게 동작하도록 SLS §6.26.3의 오버로드 해석 규칙을 다음과 같이 수정했어요.

다음 문장

Otherwise, let S1,...,Sm be the vector of types obtained by typing each argument with an undefined expected type.

을 다음 문단으로 바꿔요.

Otherwise, let S1,...,Sm be the vector of known types of all argument types, where the known type of an argument E is determined as followed:

  • If E is a function value (p_1, ..., p_n) => B that misses some parameter types, the known type of E is (S_1, ..., S_n) => ?, where each S_i is the type of parameter p_i if it is given, or ? otherwise. Here ? stands for a wildcard type that is compatible with every other type.
  • Otherwise the known type of E is the result of typing E with an undefined expected type.

패턴 매칭 클로저(closure)

{ case P1 => B1 ... case P_n => B_n }

는 함수 값

x => x match { case P1 => B1 ... case P_n => B_n }

으로 확장된 것처럼 취급돼요. 그래서 이 경우에도 ? => ? 타입으로 근사화돼요.

기본 인자는 더 이상 우선순위 결정에 영향이 없어요 (Default Arguments Are No longer Relevant for Prioritization)

Scala 2에서는 적용 가능한 여러 대안 중 하나에 기본 인자가 있으면, 그 대안은 고려 대상에서 제외됐어요. 불행한 부작용으로, 메서드의 매개변수에 기본값을 추가하면 그 메서드가 오버로드된 호출에서 보이지 않게 될 수 있었죠.

Scala 3에서는 이 구분을 없앴어요. 기본 매개변수를 가진 메서드가 다른 메서드보다 낮은 우선순위로 취급되지 않아요.

더 알아보기 (Learn more)