합성(Composition)에 관해 알아보도록 하겠습니다.
이전 글 순수함수(Pure Function), Functional Programming in Swift
함수의 합성이란
함수의 반환값이 다른 함수의 파라미터로 사용되는 것을 말합니다.
생각해보면 Composition이 되기 위해서는 함수의 반환값이 받아들이는 함수의 파마리터의 값과 동일한 타입이여야겠죠?
1. 기본 합성
예제를 통해 빠르게 이해를 해보도록 하겠습니다.
func multiple(_ num: Int) -> Int {
return num * 2
}
func numToStr(_ num: Int) -> String {
return "\(num)"
}
numToStr(multiple(100))
//200
위의 코드는 multiple의 결과가 numToStr함수의 파라미터에 전달되서 사용되고 있습니다.
이것이 바로 multiple과 numToStr이 합성(Composition)되었다고 말합니다.
함수도 일급객체이기 때문에 당연하게도 multiple의 반환값과, numToStr의 파라미터의 타입이 서로 같은걸 볼 수 있습니다.
2. 고차함수를 사용한 합성
이번에는 다른방식으로 위의 두 함수를 파마리터로 받아서 동일한 결과값을 나타내는 함수를 하나 만들어 보겠습니다.
func compositionFunction1(_ p1: @escaping (Int) -> Int, _ p2: @escaping (Int) -> String) -> String {
return p2(p1(100))
}
compositionFunction1(multiple(_:), numToStr(_:))
//200
위의 compositionFunction1함수는 2개의 함수를 파라미터로 받고 String을 리턴하는 함수입니다.
그냥 함수 두개를 파라미터로 받았지, Input값을 함수 내부에서 처리해주고있어 재활용이 불가능한 이상한 함수입니다.
그럼 어떻게 해야될까요? compositionFunction1 함수는 값을 받을 Input값이 있어야 재활용이 가능하지 않을까요?
사실 클로저 표현이 좀 복잡해지고 처음 접했을때 쉽게 이해가 되지 않을수 있어서 이상한 함수를 만들어 놓은겁니다.
차근차근 살펴 보겠습니다.
func compositionFunction2(_ p1: @escaping (Int) -> Int, _ p2: @escaping (Int) -> String) -> (Int) -> String {
return { num in
return p2(p1(num))
}
}
compositionFunction2(multiple(_:), numToStr(_:))(30)
왜이렇게 -> 많아...
이해가 되시나요?
compositionFunction1 함수에서 -> (Int) -> String 부분이 추가가 됬습니다.
-> (Int) -> String 에 대해서 설명을 드리자면, 쉽게 클로저는 ()는 Input을 나타내고 그 다음 -> 부분은 리턴타입을 의미합니다.
즉, (Int) 타입의 Input을 받고 -> String 타입의 리턴값을 의미합니다
그러면
compositionFunction2(multiple(_:), numToStr(_:))(30)
호출 부분이 이해가 되시나요?
아니면 좀 더 쉽게 나누면 더 이해가 되실까요?
let value = compositionFunction2(multiple(_:), numToStr(_:))
let result = value(30)
print(result) // 60
둘다 동일한 호출 방법입니다.
이렇게 하면 원하는 Input값을 넣어서 재활용하는 함수가 되겠죠?
multiple함수와 numToStr함수를 합성해서 compositionFunction2라는 함수를 만들고 한번에 사용하는 예제를 알아 봤습니다.
3. 제네릭을 이용한 합성
좀 더 나아가서 제네릭(Generic)을 사용하여 범용적으로 합성함수를 생성하는 방법에 대해 알아보도록 하겠습니다.
func genericComposition<T,U,V>(_ p1: @escaping (T) -> U, _ p2: @escaping (U) -> V) -> (T) -> V {
return { num in
return p2(p1(num))
}
}
genericComposition(multiple, numToStr)(30)
T, U, V라는 제네릭 함수를 이용해서 만들어 보았습니다.
T는 Input으로 받는 Int타입으로 p1타입에서 U는 리턴값으로 사용되고, p2의 Input값으로 사용되서 V타입으로 되는걸 알 수 있습니다.
(T)는 p1의 Input값과 동일한것으로 보아 p1의 Input값과 같은 타입이라는걸 알 수 있겠죠?
제네릭의 순서를 보면 genericComposition의(T) -> p1의 (T) -> p1의 U -> p2의 (U) -> p2의 V -> genericComposition의 V인것을 알 수 있습니다.
이상으로 예제와 함께 합성함수에 대해 알아보았습니다 :]
'Swift' 카테고리의 다른 글
[Swift] Codable - Decoding 방법 (1) | 2020.01.01 |
---|---|
[Swift] Codable - Encoding 방법 (0) | 2019.12.30 |
[Swift] Swift Style Guide 정리 (1) | 2019.07.29 |
[Swift] 1. 순수함수, Pure Function (Functional Programming in Swift) (0) | 2019.07.25 |
[Swift] 문자열 다루기 (0) | 2019.07.25 |