E183: Closure Cannot Have Internal Parameter Dependencies — 클로저는 내부 파라미터 의존성을 가질 수 없음
E183: Closure Cannot Have Internal Parameter Dependencies — 클로저는 내부 파라미터 의존성을 가질 수 없음
한 파라미터의 타입이 같은 파라미터 목록의 다른 파라미터에 의존하는 클로저(익명 함수)를 만들려 할 때 발생하는 에러예요. 이를 "파라미터 의존성(parameter dependency)"이라고 부르며, 클로저에서는 지원되지 않아요.
본문
Scala에서 클로저는 Function1, Function2 같은 함수 타입으로 변환돼요. 이런 표준 함수 타입은 파라미터 타입이 다른 파라미터를 .type(싱글턴 타입)으로 참조하는 의존적 파라미터 타입(dependent parameter type)을 표현할 수 없어요.
이 제한은 다형 클로저(타입 파라미터가 있는 [T] 형태)와 단형(monomorphic) 클로저 모두에 적용돼요.
예시 (Example)
def example = [T] => (x: T, y: List[x.type]) => List(y)
여기서 파라미터 y의 타입이 List[x.type]인데, 이것은 파라미터 x의 값에 의존해요. 같은 목록 안의 파라미터들 사이의 이런 내부 의존성 때문에 이 클로저를 표준 함수 타입으로 표현할 수 없어요.
에러 (Error)
-- [E183] Type Error: example.scala:1:18 ---------------------------------------
1 |def example = [T] => (x: T, y: List[x.type]) => List(y)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|cannot turn method type [T](x: T, y: List[(x : T)]): List[List[(x : T)]] into closure
|because it has internal parameter dependencies
해결 방법 (Solution)
이 제한을 우회하는 흔한 방법은 두 가지예요:
1. 클로저 대신 일반 메서드 사용하기
클로저를 이름 있는 메서드 정의로 바꾸세요:
def example[T](x: T, y: List[x.type]): List[List[x.type]] = List(y)
2. 커리된 파라미터 사용하기
의존적인 파라미터들을 서로 다른 파라미터 목록으로 나누세요. 그러면 의존하는 파라미터가 앞 목록의 파라미터를 참조할 수 있어요:
def curriedExample = [T] => (x: T) => (y: List[x.type]) => List(y)
이렇게 하면 각 파라미터 목록이 별개의 클로저를 만들어내고, 내부 클로저는 파라미터 간 의존성이 아니라 둘러싼 스코프에서 x를 캡처하기 때문에 동작해요.
더 알아보기
파라미터 타입이 다른 파라미터에 의존하면 클로저(익명 함수)로는 표현할 수 없어요. 명명된 메서드나 커링으로 우회하면 돼요.