Computer >> 컴퓨터 >  >> 스마트폰 >> iPhone

Swift 함수 합성(Function Composition) 쉽게 이해하기: 수학적 개념부터 실전 구현까지

개발자라면 매일 함수를 다루게 됩니다. 함수는 특별한 유형의 관계를 나타내는데, 함수가 받는 모든 입력값은 어떤 출력값과 연결되어 있습니다. 좀 더 일반적으로 표현하면, 함수는 입력값을 하나의 출력값으로 매핑(mapping)하는 규칙이라고 할 수 있습니다.

함수 합성(function composition)의 기본 아이디어는 한 함수의 결과에 다른 함수를 적용하는 것입니다. 즉, 여러 함수를 하나의 함수로 결합하는 수학적 개념입니다.

함수 합성의 수학적 개념

수학적 개념과 함께 자세히 살펴보겠습니다. f와 g가 두 개의 함수라고 할 때, 이 함수들은 다음과 같이 표현할 수 있습니다.

f: A -> B
g: B -> C

이 두 함수를 합성하면 "g ∘ f"(g of f라고 읽음)로 표현할 수 있습니다.

(g ∘ f): A -> C
(g ∘ f)(a) = g(f(a)) for all a in A

간단한 예제를 통해 더 깊이 이해해 보겠습니다.

f(a) = 2a + 3
g(a) = 3a + 5

두 함수를 합성하면 다음과 같은 결과가 나옵니다.

(g ∘ f)(a) = g(f(a))
          = 3(f(a)) + 5
          = 3(2a + 3) + 5
          = 6a + 14

이 개념은 수학에만 국한되지 않습니다. 프로그래밍 언어에서도 적용할 수 있으며, 이러한 패러다임을 지원하는 언어를 함수형 프로그래밍 언어라고 부릅니다. 함수 합성 개념을 이해하면 코드의 가독성이 크게 향상되고, 다른 개발자들도 코드를 훨씬 쉽게 파악할 수 있습니다.

함수형 프로그래밍 언어로서의 Swift

다행히 Swift도 함수형 프로그래밍 언어입니다. Swift 프로그래밍에서 함수는 가장 중요한 역할을 담당하므로, 우리는 매일 함수와 상호작용하게 됩니다. Swift 함수는 값을 반환할 수 있으며, 그 반환값을 다른 함수의 입력으로 전달할 수 있습니다. 이는 실무에서 널리 사용되는 일반적인 프로그래밍 방식입니다.

Swift에서 함수 합성 구현하기

정수 배열이 주어졌을 때, 고유한(unique) 짝수 정수들의 제곱으로 이루어진 배열을 결과로 얻고 싶다고 가정해 보겠습니다. 일반적으로는 다음과 같이 함수를 구현하게 됩니다.

이 코드는 올바른 결과를 출력하지만, 보시다시피 가독성이 좋지 않습니다. 게다가 함수 호출 순서가 우리가 생각하는 순서와 반대로 보이기 때문에, 초보 개발자에게는 혼란을 줄 수 있습니다. 이런 코드 블록은 분석하기도 어렵습니다.

바로 이럴 때 함수 합성이 위 문제들을 해결해 줍니다. Swift에서는 제네릭(generics), 클로저(closure), 중위 연산자(infix operator)를 활용하여 함수 합성을 구현할 수 있습니다.

그럼 해당 코드 블록에서 어떤 일이 일어나고 있는지 단계별로 살펴보겠습니다.

  1. 커스텀 중위 연산자 ">>>"를 선언합니다. 이 연산자는 + 연산자처럼 왼쪽 결합성(left associativity)과 우선순위(precedence order)를 가집니다.
  2. 중위 연산자와 같은 이름의 함수를 선언합니다. 이 함수는 세 개의 제네릭 타입 T, U, V를 사용하며, 두 개의 클로저를 입력 매개변수로 받습니다.
  3. 왼쪽 매개변수는 클로저로, T 타입의 입력을 받아 U 타입의 출력을 반환합니다.
  4. 오른쪽 매개변수 역시 클로저로, U 타입의 입력을 받아 V 타입의 출력을 반환합니다.
  5. >>> 함수는 (T) → V 타입의 함수(클로저)를 반환합니다. 즉, 최종 클로저는 T 타입의 입력을 받아 V 타입의 출력을 돌려주며, 이때 왼쪽 매개변수의 출력이 오른쪽 매개변수의 입력으로 연결됩니다.
  6. 함수 본문에서는 왼쪽 매개변수의 실행 결과에 오른쪽 매개변수를 적용한 값을 반환합니다.
left :  (T) -> U
right: (U) -> V
Output Type: (T) -> V

함수 합성의 수학적 표현을 이해하고 있다면, Swift의 구현이 수학적 정의와 정확히 동일하다는 것을 바로 알아차릴 수 있습니다.

이제 동일한 결과(고유한 짝수 정수들의 제곱 배열)를 함수 합성을 통해 얻을 수 있습니다.

결국 이것은 같은 결과를 반환하는 함수들의 체인(chain)입니다. 함수 호출 순서가 이제 사람이 사고하는 자연스러운 흐름과 일치하게 되었고, 가독성이 크게 향상되어 누구나 코드를 쉽게 이해할 수 있게 되었습니다.

읽어주셔서 감사합니다!