Higher-Order Functions
고차함수는 다른 함수를 전달인자로 받거나
함수 실행의 결과를 함수로 반환하는 함수를 말한다.
Swift 의 함수(클로저) 는 일급 시민이기 때문에
함수의 전달인자로 전달할 수 있으며, 함수의 결과값으로 반환할 수 있다.
가장 잘 알려진 고차함수로는
map
, compactMap
, flatMap
, reduce
, filter
등이 있다.
map
map
함수는 배열의 요소를 변환하는 고차함수이다.
// example "map"
let numbers = [10, 30, 91, 50, 100, 39, 74]
var formattedNumbers: [Stirng] = []
for number in numbers {
let formattedNumber = "\(number)$"
formattedNumbers.append(formattednumber)
}
let mappedNumbers = number.map{ "\($0)$" }
위의 예시를 보면
변수 formattedNumbers
와 mappedNumbers
의 값은
["10$", "30$", "91$", "50$", "100$", "39$", "74$"]
으로 같다.
formattedNumbers
는 for
문을 통해
numbers
의 요소를 순회하면서 "\(number)$"
의 형태로 바꿔준 뒤
append
메소드를 사용하여 값을 넣어주었다.
반면 mappedNumbers
는 고차함수 map
을 활용하여
좀 더 간단하게 처리를 할 수 있었다.
filter
filter
함수는 요소가 결과에 포함되어야하는지를 나타내는
Bool
값을 리턴하는 함수가 내장되어있다.
// example "filter"
let evenNumbers = numbers.filter { $0 % 2 == 0 }
위의 예시는 고차함수 filter
를 활용하여
number
에 있는 짝수만을 상수 evenNumbers
에 넣도록 하였다.
filter
를 사용하지 않았다면
위의 map
의 예시와 같이 배열을 순회하면서
짝수인지 확인하는 조건을 추가하여
짝수만을 담을 변수에 append
해주었을 것이다.
reduce
reduce
함수는 배열을 단일값으로 줄일 수 있다.
let total = numbers.reduce(0) { $0 + $1 }
위의 예시는 상수 total
에 numbers
의 요소들의 합을 넣도록 하고 있다.
고차함수 reduce
는 두 개의 매개변수를 요구하는데
시작값과 합계 함수가 이에 해당한다.
예시에서 reduce
뒤에 (0)
이 바로 시작값이 되고
{ $0 + $1 }
이 합계 함수가 된다.
예시를 다음과 같이 다르게 표현할 수도 있다.
let total = numbers.reduce(0, +)
compactMap
compactMap
함수는 배열안에 nil
값이 있을 때 유용하다.
다음 예시는 배열 안에 있는 문자열들을 대문자로 바꾸고 있다.
// example no "compactMap"
let words: [String?] = ["room", "home", nil, nil, "green"]
let uppercasedWords = words.map({ word -> String? in
if let word = word {
return word.uppercased()
} else {
return nil
}
})
앞서 배웠던 map
을 활용한다면 아래의 표현도 가능하다.
// example no "compactMap"
let uppercasedWords = words.map{ $0 != nil ? $0.uppercased() : nil }
위의 두 예시는 모두 compactMap
을 사용하지 않았기때문에
nil
에 대한 처리를 따로 해주었다.
// example "compactMap"
let uppercasedWords = words.compactMap { $0?.uppercased() }
이번에는 compactMap
을 적용해보았다.
compactMap
은 배열의 모든 요소를 순회하면서 nil
이 아닌 값에
원하는 연산을 할 수 있다.
flatMap
flatMap
함수는 어떤 배열이든 1차원 배열로 변환한다.
// example no "flatMap"
let words: [[String]] = [["room", "home"], ["train", "green"]]
var singleArray: [String] = [String]()
for individualArray in words {
for word in individualArray {
singleArray.append(word)
}
}
위의 예시는 words
라는 2차원 배열을 1차원 배열로 변환하고 있다.
이중 for
문으로 배열을 순회하면서 변수 singleArray
에 요소를 넣어주고 있다.
flatMap
을 활용하면 좀 더 간단하게 표현할 수 있다.
let singleArray = words.flatMap { $0 }
📚 Reference
Higher-Order Functions in Swift
Swift Functional Programming - Second Edition Dr. Fatih Nayebi
yagom's Swift Basic