➰ 🍎🍏🍎🍏/iOS

[Swift] Closure와 고차함수(filter, reduce, map, sort, forEach)

 사과개발자 2021. 7. 28. 23:12

Closure란?


클로저는 중괄호({})로 감싸진 실행 가능한 코드 블럭입니다.

func helloGenerator(message: String) -> (String, String) -> String {
  return { (firstName: String, lastName: String) -> String in
    return lastName + firstName + message
  }
}

함수와는 다르게 함수 이름 정의가 따로 존재하지 않습니다. 하지만 파라미터를 받을 수 있고, 반환 값이 존재할 수 있다는 점에서 함수와 동일합니다. 즉, 함수는 이름이 있는 클로저입니다. 클로저는 in 키워드를 사용해서 파라미터, 반환 타입 영역과 실제 클로저의 코드를 분리하고 있습니다.

Swift 컴파일러의 타입 추론 덕분에, helloGenerator() 함수에서 반환하는 타입을 가지고 클로저에서 어떤 파라미터를 받고 어떤 타입을 반환하는지를 알 수 있어 아래와 같이 코드는 간결화 할 수 있습니다.

func helloGenerator(message: String) -> (String, String) -> String {
  return { firstName, lastName in
    return lastName + firstName + message
  }
}

놀라운 사실은 여기서 생략할 수 있는게 더 있다는 사실입니다. 마찬가지로 타입 추론 덕분에 첫 번째 파라미터가 문자열이고, 두 번째 파라미터도 문자열이라는 것을 알 수 있습니다. 첫 번째 파라미터는 $0, 두 번째 파라미터는 $1로 바꿔서 쓸 수 있습니다.

func helloGenerator(message: String) -> (String, String) -> String {
  return {
    return $1 + $0 + message
  }
}

클로저 내부의 코드가 한 줄이라면, return까지도 생략해버릴 수 있습니다.

func helloGenerator(message: String) -> (String, String) -> String {
  return { $1 + $0 + message }
}

 

고차함수란?


고차함수란 매개변수로 함수를 갖는 함수입니다.
고차함수를 사용하게 되면 함수의 내부 코드를 건드리지 않고도 외부에서 실행 흐름을 추가할 수 있어 함수의 재활용성, 재사용성 의 이점을 얻을 수 있습니다.

 

고차함수의 종류


1. sort()

정렬된 배열 반환

let numbers = [1, 3, 2, 6, 7, 5, 8, 4]

let sortedNumbers = numbers.sort { $0 < $1 }
print(sortedNumbers) // [1, 2, 3, 4, 5, 6, 7, 8]

2. filter()

true 인것만 골라낸 배열 반환

let numbers = [1, 3, 2, 6, 7, 5, 8, 4]

let evens = numbers.filter { $0 % 2 == 0 }
print(evens) // [2, 6, 8, 4]

3. map()

배열의 요소들에게 클로저를 실행시킨 배열 반환

let numbers = [1, 3, 2, 6, 7]

let mappedNumbers = numbers.map { $0 * 2 }
print(mappedNumbers) // [2, 6, 4, 12, 14]

4. reduce()

주어지는 인덱스의 값과 클로저 실행결과,
그리고 그 결과와 두번째 요소의 클로저 실행결과
...
마지막까지 실행한 후의 결과 반환

let arr1 = [1, 3, 6, 2, 7, 9]
arr1.reduce(0) { $0 + $1 } // 1 + 3 + 6 + 2 + 7 + 9 ==> 28

아래와 같이 + 라는 클로저를 넘기는 것도 가능합니다.

arr1.reduce(0, +) // 28

5. forEach()

forEach에서는 break, continue 구문을 사용할 수 없고,return을 통해서 빠져나갈 수 있습니다. (continue처럼 동작함)
for-in에서는 break, continue을 사용할 수 있고,return을 이용해서 빠져나오려면 에러가 납니다.

let array = [1,2,3,4,5]

for num in array {
    print(num)
}

<출력>
//1
//2
//3
//4
//5

array.forEach {
    print($0)
}

<출력>
//1
//2
//3
//4
//5
반응형