🌟 고차 함수는
"다른 함수를 전달인자로 받거나 함수실행의 결과를 함수로 반환하는 함수"이다.
Swift에서 함수는 1급 객체이기 때문에 함수를 전달 인자로 보내거나, 변수/상수로 저장 혹은 전달하거나, 함수의 반환값으로 쓸 수 있다.
이 때, 다른 함수를 전달인자로 받거나, 함수실행의 결과를 함수로 반환하는 함수가 고차함수의 정의인 것이다.
Swift에서 특히 자주 사용하는 고차함수로 map, filter, reduce, compactMap, flatMap이 있다.
map 함수는 컨테이너 내부의 기존 데이터를 변형하여 새로운 컨테이너를 생성한다.
여기서 Array, Set, Dictionary와 같은 자료구조들이 일종의 컨테이너라고 할 수 있다.
시간복잡도는 O(n)이며, n은 컨테이너의 길이이다.
let numbers: [Int] = [0, 1, 2, 3, 4]
var doubledNumbers: [Int]
doubledNumbers = numbers.map { $0 * 2 }
print(doubledNumbers) // [0, 2, 4, 6, 8]
filter 함수는 컨테이너 내부의 값을 걸러서 새로운 컨테이너로 추출한다. 시간복잡도는 O(n)이며, n은 컨테이너의 길이이다.
let numbers: [Int] = [0, 1, 2, 3, 4]
let oddNumbers: [Int] = numbers.filter {
$0 % 2 != 0
}
print(oddNumbers) // [1, 3]
reduce함수는 컨테이너 내부의 콘텐츠를 하나로 통합한다. 시간복잡도는 O(n)이며, n은 컨테이너의 길이이다.
let someNumbers: [Int] = [2, 8, 15]
let sumFromThree = someNumbers.reduce(3) { $0 + $1 }
print(sumFromThree) // 28
flatMap함수는 2차원 배열을 1차원 배열로 flat하게 만들어주고 싶을 때 사용한다. 시간복잡도는 O(n+m)이며, n은 배열의 길이 m은 결과값의 길이이다.
let scores = [[5,2,7], [4,8], [9,1,3]]
let allScores = scores.flatMap { $0 } // [5, 2, 7, 4, 8, 9, 1, 3]
let passMarks = scores.flatMap { $0.filter { $0 > 5} } // [7, 8, 9]
compactMap함수는 1차원 배열에서 nil값을 제거하고, 옵셔널 바인딩을 해준다. 시간복잡도는 O(n+m), n은 배열의 길이 m은 결과값의 길이이다.
let array = [1,2,nil,10,123,nil,nil]
let cmapTest = array.compactMap{ $0 } //[1, 2, 10, 123]
Swift 의 고차함수에서 가장 많이 쓰이는 함수들을 알아봤다.
그리고 함수형 프로그래밍 개념 중 Maybe
와 Either
라는 개념이 있다.
상황에 따라 두 가지 타입의 결과값을 가지는 경우 주로 사용한다.
Maybe는 값이 있을 수도 있고, 없을 수도 있다는 개념이다. Swift에서는 Optional
이라는 이름으로 이 개념이 구현되었다.
간단하게 예제를 보자면
var maybeString: String? = "maybe"
print(maybeString) // 출력: Optional("maybe")
maybeString = nil
print(maybeString) // 출력: nil
Either는 두 가지 타입을 가질 수 있는 경우에 사용한다. 주로 성공과 실패, 또는 두 가지 다른 유형의 반환값을 처리할 때 사용된다.
swift로 success or failure에 대해 구현하자면 아래와 같다.
enum Either<T, U> {
case left(T)
case right(U)
}
let success = Either<Int, String>.left(200)
let failure = Either<Int, String>.right("Error")
switch success {
case .left(let value):
print("Success with value \(value)")
case .right(let error):
print("Failure with error \(error)")
}
이 Either의 개념을 가지고 나타난 것이 바로 swift의 Result이다.
Result란 Either에서 성공/Error로 제한을 걸어 사용하는 자료구조인 것이다.