# 고차함수(Higher-order function) 개념
고차함수는 함수를 파라미터로 받거나 함수를 리턴하는 함수를 의미한다.
고차함수 종류에는 다음과 같은 것들이 있다.
- map
- filter
- reduce
- forEach
- compactMap
- flatMap
- ...etc
# map
let numbers = [1,2,3,4,5]
// 타입에 대한 설명
// numbers.map(transform: (Int) throws -> T)
// 실제 호출
numbers.map{ item in
item + 1
} // [2,3,4,5,6]
let newArr = numbers.map{ $0 + 1 } // [2,3,4,5,6]
map함수의 파라미터로 전달되는 클로저는 Int형 인풋에 대해 어떠한 타입이든 상관없이 리턴값을 내보낸다. throws -> T
의 T
가 모든 타입에 대해 나타내는 것이라고 생각하면 됨
자바스크립트 map 메서드와 동일함. 스위프트 map도 immutable함. (값이 복사)
map함수의 클로저는 인풋데이터 타입으로부터 T타입 리턴이 결정되어 있기 때문에 클로저 작성 시 타입 표기는 생략해도 됨
# filter
자바스크립트 filter와 동일하다. 클로저 인풋으로 각 원소가 전달되고 클로저 리턴타입으로 불리언 타입 값이 나타나면 된다. 불리언 리턴값이 참인 요소들만 원래 컬렉션에서 빼온다.
let names = ["Apple", "Black", "Circle", "Dream", "Blue"]
let newArr = names.filter{ item in
item.contains("A")
}
# reduce
누적값을 계산하는 자바스크립트 reduce와 동일. 스위프트에서 reduce
는 첫 번째 파라미터로 초기값을 받는다.
두 번째 파라미터로 어떤 연산을 할 지에 대한 클로저를 전달하면 된다.
해당 클로저의 첫 번째 파라미터는 연산 이후의 초기값을 의미하고 두 번째 파라미터는 순회하는 다음 요소의 값을 의미한다.
numbersArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
// 1. 홀수만 filter로 뽑아서
// 2. 각 원소를 map으로 제곱한 뒤
// 3. 모든 요소값의 합을 출력해보자
let result = numbersArray.filter{ item in
item % 2 == 1
}.map{ $0 * $0 }.reduce(0){ prev, nextValue in
prev + nextValue
}
print(result)
# forEach
컬렉션 각 요소를 순회하며 작업을 진행한다. 클로저 타입은 (인풋타입) -> Void
임을 참고하자.
let arr = [1,2,3]
arr.forEach{ item in
print(item + 1)
}
# compactMap
기존 map 함수에 옵셔널 요소는 제거하고 나머지 옵셔널 스트링에 대해서는 if let 바인딩까지 해주는 기능이 추가된 함수이다.
// stringArray는 옵셔널 스트링 타입
let stringArray: [String?] = ["ABC", nil, "HELLO", nil]
let newArr = stringArray.compactMap{ $0 }
print(newArr) // "ABC", "HELLO
// nil값은 필터링되어 없는것이 확실하니
// 강제 언래핑 적용 가능
let newArr2 = stringArray.filter{ $0 != nil }.map{ $0! }
# flatMap
자바스크립트 flat메서드와 동일하다. 중첩배열 평탄화를 처리해줌
let nestedArr = [[1,2,3], [1,2]]
print(nestedArr.flatMap{ $0 })
명령형 프로그래밍 vs 함수형(선언형) 프로그래밍
명령형 프로그래밍과 함수형 프로그래밍의 차이는 구현을 위한 사고 방식의 차이에 있다.
특정 로직 구현을 위해 밑바닥부터 구현하는 프로그래밍 방식을 명령형, 기존 함수들 및 모듈을 조합하여 결과를 구현하고자 하는 것을 함수형 프로그래밍이라고 생각하면 된다.
swiftUI에서 함수형 프로그래밍 방식을 채택한다.
// 배열의 합 구하기 - 명령형
let numbers = [1, 2, 3]
var sum = 0
for number in numbers {
sum += number
}
print(sum)
// 배열의 합 구하기 - 함수형
let newNnumbers = [1, 2, 3]
var newSum = 0
newSum = newNnumbers.reduce(0) { $0 + $1 }
print(newSum)