# 고차함수(Higher-order function) 개념

고차함수는 함수를 파라미터로 받거나 함수를 리턴하는 함수를 의미한다.

고차함수 종류에는 다음과 같은 것들이 있다.

  1. map
  2. filter
  3. reduce
  4. forEach
  5. compactMap
  6. flatMap
  7. ...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 -> TT가 모든 타입에 대해 나타내는 것이라고 생각하면 됨

자바스크립트 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)

# Reference

  1. 인프런 - 앨런 swift 문법 마스터 스쿨 (opens new window)
  2. 얄팍한 코딩 사전 - 함수형 프로그래밍이란 (opens new window)
  3. 곰튀김 - 함수형 프로그래밍 세션 1 (opens new window)
  4. 곰튀김 - 함수형 프로그래밍 세션 2 (opens new window)