func
선언 문법 제거커리 함수 선언 구문 func foo(x: Int)(y: Int)
은 제한된 유용성을 가지며, 언어와 구현 측면에서 많은 복잡성을 야기한다. 따라서 이 구문을 제거해야 한다.
커링 함수 문법이 존재함으로써 다른 언어 기능들도 복잡해지는 부작용이 발생한다:
표준 라이브러리, Cocoa, 그리고 대부분의 서드파티 코드의 관용구는 ML 스타일의 자유 함수 인수 커링을 활용하기 어렵게 만든다. Cocoa와 표준 라이브러리에서는 대부분의 기능이 메서드로 구성되어 있어, self.method
를 통해 유용한 부분 적용을 얻을 수 있고, 언젠가 .map { f($0) }
도 가능할 것이다. 커링 함수 디자인은 키워드 인자 모델 디자인보다 이전에 만들어졌다. 우리는 인자가 단일 튜플이라는 모델에서도 벗어날 계획이다(이미 @autoclosure
와 inout
같은 기능 때문에 이 모델은 사실상 무의미하다). 이는 ML 인자 모델과 더욱 멀어지게 한다.
많은 사용자가 커링 기능의 무용지물함을 지적하며, Scala 스타일의 f(_, 1)
과 같은 자유로운 부분 적용을 대안으로 요청했다. 함수형 프로그래밍 지향적인 사용자조차 우리의 커링 기능에 큰 가치를 느끼지 못한다는 사실은, 이 기능이 없어도 괜찮을 것 같다는 생각이 들게 한다. 이 기능은 분명히 “이미 가지고 있지 않다면 추가할까?“라는 질문에 통과하지 못한다.
func
선언에서 여러 인자 패턴을 지원하는 기능을 제거한다. 이에 따라 func-signature
문법을 단순화하여 단일 argument
절만 허용하도록 변경한다. 마이그레이션을 위해 기존의 커링 선언 구문을 사용하는 코드는 명시적으로 클로저를 반환하도록 변환할 수 있다:
// 변경 전:
func curried(x: Int)(y: String) -> Float {
return Float(x) + Float(y)!
}
// 변경 후:
func curried(x: Int) -> (String) -> Float {
return {(y: String) -> Float in
return Float(x) + Float(y)!
}
}
메서드의 의미를 변경하지는 않는다. 메서드는 여전히 Self -> Args -> Return
타입의 함수로 정의된다.
이 변경 사항은 언어 기능을 제거하는 것이므로, 해당 기능을 사용하는 기존 코드가 동작하지 않게 된다. 커링(Currying)은 그 유용성이 상대적으로 제한적이며, 최신 언어 트렌드와도 맞지 않는다. 또한 자동 마이그레이션을 통해 어느 정도 해결할 수 있기 때문에, 언어를 단순화하기 위한 대가로 이러한 영향은 감수할 만하다고 판단했다.
대안은 현재 커링 방식을 그대로 유지하는 것이다. 하지만 앞서 논의했듯이 이 방식은 이상적이지 않다. 즉각적인 조치를 취할 필요는 없지만, 향후 더 관용적인 방식으로 유사한 기능을 제공할 수 있는 대안적인 설계가 가능하다.
foo(_, bar: 2)
는 { x in foo(x, bar: 2) }
의 축약형으로 사용할 수 있다. 이 방식은 키워드 인자 중심의 API 설계에서 더 읽기 쉬운 장점이 있다. 또한 전통적인 커링보다 유연하며, API 설계자가 인자 순서를 미리 고려할 필요가 없다.self.method
는 메서드를 self
파라미터에 부분적으로 바인딩한다. 여기에 .method(argument)
를 추가해 메서드를 self
가 아닌 인자에 부분적으로 바인딩할 수 있다. 이는 map
이나 filter
같은 고차 함수에서 특히 유용하다. Haskell 스타일의 (2+)
/(+2)
문법을 도입해 연산자를 부분 적용하는 것도 고려할 만하다.