So I’ve been using Swift for a while now. I started back at the end of 2014 and for the first while I essentially treated it like Objective-C with different syntax. While functional, its not FUNCTIONAL. What I mean is that functions are first class citizens in swift and the swift language itself is a functional language. There are three great examples of this when working with arrays these are the filter, map, and reduce methods
filter
When dealing with arrays I’ve been in the habit of simply creating new arrays, iterating over my array to create my new array and moving on with my life. For example, say I had an array of numbers and wanted to find all the numbers above a certain amount. I might tackle this like so:
let numbers = (1...10) var numsGT4 = [Int]() for num in numbers { if num > 4 { numsGT10.append(num) } } //numsGT4: [5, 6, 7, 8, 9, 10]
One problem with this is that numsGT4 is declared as a var, even if I didn’t want it to be alterable after creation. Swift has a great function called filter that not only fixes this, but also simplifies my code:
let numbers = (1...10) let numsGT4 = numbers.filter { (num) -> Bool in return nun > 4 }
Or, in an even more simplified form:
let numsGT4 = numbers.filter{$0 > 4}
Easy peasy lemon squeezy! But the great thing is that the filter method takes another method as input and constructs an array from the results of that method. So while the above example is perhaps a bit simplistic, it works for anything, classes, structs, you name it!
map
But lets say, instead of filtering your list, you would like to perform some action on it. Again, I used to create arrays and simply iterate through my array, altering the values as they came and stuffing them into another array. Functional swift comes to the rescue again with the map function! For our example lets take the numbers array above and simply double their value (multiply each by 2). My old (bad) way:
var numbersDoubled = [Int]() for num in numbers { numbersDoubled.append(2 * num) } // numbersDoubled: [2,4,6,8,10,12,14,16,18,20]
Using map:
let numbersDoubled = numbers.map { (num) -> Int in return num * 2 }
More simply:
let numbersDoubled = numbers.map { $0 * 2}
Again, the map function takes another function as input! Neat!
reduce
Lets say we want to take our array and reduce it to one single value. For example lets take all the numbers in our array and sum them up. Old way:
var sum = 0 for num in numbers{ sum += num } // sum: 55
The functional (correct) way:
let sum = numbers.reduce(0) { (finalValue, num) -> Int in return finalValue + num }
Reduce is a bit more tricky than the other two methods, so lets look at its signature:
func reduce<Result>(_ initialResult: Result, _ nextPartialResult: (Result, Element) throws -> Result) rethrows -> Result
so we pass in an initial value of type Result (in our case it is the Int value 0). Then the function takes in a function that itself has a signature of (Result, Element) throws -> Result. In our case this becomes (Int, Int)->Int. and finally the reduce function itself returns they type Result (again, Int in our case). Not to bad. Also, understanding this means that if we use our head we can simply our code even more!
let sum = numbers.reduce(0){$0+$1}
Or, if we realize that the ‘+’ operator is actually a function with signature of (Int,Int)->Int, we can simplify further:
let sum = numbers.reduce(0,+)
Try it out! Its been great fun learning to do things more functionally!