syntax of the reduce method in Swift

Hi,


Working on a simple problem where I want to sum all the elements in an int array. All the numbers in the array are positive. I came accross the reduce method online and I noticed the following syntax:


let items = [2, 4, 5, 7]
let sum = items.reduce(0, +)    // result is 18


I understand that the first argument is the initial result (in my case 0). I'm having a hard time understand the nextPartialResult closure which is the second argument. I also don't understand the "+" syntax, I'm guessing that shorthand for summing all the elements in the array. I don't want to just use that code without understanding what it means...Any help would be appreciated!


Thanks!

Post not yet marked as solved Up vote post of mkhan094 Down vote post of mkhan094
1.9k views

Replies

This writing is the result of a series of implicit declaration, thanks to the smart Swift compiler.


Let's look how we go from the most extensive form to the very short one.

Test it all in playground, to see it working.


The very long form is:

let sum = items.reduce(0, { (total:Int, value:Int) -> Int in total + value })


The closure may be moved after the ()

let sum = items.reduce(0) { (total:Int, value:Int) -> Int in total + value }


As type (Int) may be infered because array of Int, you can remove types declarations:

let sum = items.reduce(0) { (total, value) in total + value }


Now, we don't need parenthesis either:

let sum = items.reduce(0, { total, value in total + value })

or

let sum = items.reduce(0) { total, value in total + value }


We can also use shorthands to identyify parameters:

let sum = items.reduce(0, { $0 + $1 })

or

let sum = items.reduce(0) { $0 + $1 }


and finally, when closure is inside (), as arguments $0 and $1 can be deduced, we can just write the shortest form:

let sum = items.reduce(0, +)


Imagine now you want to sum the squares; the compact form does not work.

You should write at least:

let sumSquares = items.reduce(0)  { $0 + $1*$1 }


But you could also first map the array to the squares, and use the compact reduce !

let sumSquares = items.map({$0*$0}).reduce(0, +)


Mastering those func map, reduce, filter and some other is really useful. You could read these tutorials:

h ttps://useyourloaf.com/blog/swift-guide-to-map-filter-reduce/

h ttps://medium.com/@abhimuralidharan/higher-order-functions-in-swift-filter-map-reduce-flatmap-1837646a63e8

Do you know that function name works as closure in Swift?


func add(_ x: Int, to y: Int) -> Int {
    x + y
}

let items = [2, 4, 5, 7]
let sum = items.reduce(0, add)    // result is 18

When you write a function name (without parameters) where a closure of matching type is expected, you can use the function as a closure.

You can use the function `add` as a closure of type (Int, Int)->Int .


And, in Swift, operators are very similar to functions.

static func + (lhs: Int, rhs: Int)-> Int

You can use the operator `+` as a closure of type (Int, Int)->Int.

(As you know, `+` has so many overloads, which can be a closure of type (Double, Double)->Double, or some other in some other cases.)


So, it is not just a shorthand for `reduce`, but operator itself can be used as a closure at any place whare a closure can be accepted.

var f: (Int, Int)->Int = (+)
print( f(1, 2) ) //-> 3

(`Parentheses are needed to tell Swift compiler that it is not a misusage of unary operator.)