Should I Change All For Loops to Higher-Order Functions?
Nope
If intent is a pure transformation, higher-order operations is a better option than for loops. Because they are predefined method, they are concise and easy to read.
Additionally as closures are intended not to have side effects to other variables, but to have only the input and output, they are generally safer . (Of course, it’s still possible to modify captured variables inside a closure.)
1
2
3
4
5
6
7
8
9
var hello = ""
let evenNumbers = numbers
.filter {
hello = "hello"
return $0 % 2 == 0
}
.map { $0 * 2 }
print(hello) //hello
In closure of the methods, you cannot use break or continue. Also, you cannot return value of outer function. The scope is limited to the closure. If you do not want to apply to closure to all elements and just want to do some action in iteration, for loops can be a better option. See forEach for details. If you want to use continue in the closure, you can use filter + map or return nil+compactMap instead.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
func isAnagram(with string: String) -> Bool {
guard string.count == self.count else {
return false
}
var dict = self.reduce(into: [Character: Int]()) { dict, char in
dict[char, default: 0] += 1
}
for char in string {
if dict.keys.contains(char) {
dict[char, default: 0] -= 1
} else {
return false
}
}
return dict.values.allSatisfy { $0 == 0 }
}
Remember useful sequence functions, and use them when they fit your intention — instead of stretching a for loop unnecessarily:
map,flatMap,compactMap(removes nil)filterreduceallSatisfycontains
When Did Higher-Order Functions Become Popular in Swift?
map method is from Swift 1.0, 2014. But Objective-C was popular, and imperative for loop styles were used.
During 2016-2018, RxSwift/ReactiveCocoa popularize operator chains (map, filter, flatMap, scan…), normalizing declarative, side-effect-light code.
In 2018, Swift 4.1 introduced compactMap.
In 2019, SwiftUI and Combine push a declarative mindset; chains of transforms become mainstream even in non-reactive code.
Higher-order functions are now common for “transform/filter/query” over collections.
Lint rules and code reviews in many teams encourage map/filter when intent is a pure transformation.
What Does ‘Higher-Order’ Means?
Order means level
0th-order: value
1
let n: Int = 42
1st-order function: parameter and return values are values
1
func square(_ x: Int) -> Int { x * x }
Higher-order function: parameter or return values are function.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
func applyTwice(_ f: (Int) -> Int, to x: Int) -> Int {
f(f(x))
}
let doubled = applyTwice({ $0 * 2 }, to: 3) // 12
func makeAdder(_ n: Int) -> (Int) -> Int {
return { x in x + n }
}
let add5 = makeAdder(5)
add5(10) // 15
let numbers = [1, 2, 3, 4, 5]
let doubledEvens = numbers
.filter { $0 % 2 == 0 }
.map { $0 * 2 }
// [4, 8]