The following lines show an imperative code version of a for
in
loop that calculates the sum of all the highestScore
values for the games. The code file for the sample is included in the swift_3_oop_chapter_07_26
folder:
var sum = 0 for game in gameRepository.getAll() { sum += game.highestScore } print(sum)
The code is very easy to understand. The sum
variable has a starting value of 0
, and each iteration of the for in
loop retrieves a Game
instance from the Array<Game>
returned by the gameRepository.getAll
method and increases the value of the sum
variable with the value of the highestScore
property.
We can combine the map
and reduce
operations to create a functional version of the previous imperative code to calculate the sum of all the highestScore
values for the games. The next lines chain a call to map
to a call to reduce
to achieve this goal. Take a look at the following code. The code file for the sample is included in the swift_3_oop_chapter_07_27
folder:
let highestScoreSum = gameRepository.getAll().map({ $0.highestScore }).reduce(0, { sum, highestScore in return sum + highestScore }) print(highestScoreSum)
First, the code uses the call to map
to transform an Array<Game>
into an Array<Int>
with the values specified in the highestScore
stored property. Then, the code calls the reduce
method that receives two arguments that do not use parameter labels: the initial value for an accumulated value and a combine closure that will be repeatedly called with the accumulated value. The method returns the results of the repeated calls to the combine
closure.
The closure specified in the second argument for the reduce
method receives sum
and highestScore
and returns the sum of both values. Thus, the closure returns the sum of the total accumulated so far plus the highestScore
value that is processed. We can add a print
statement to display the values for both sum
and highestScore
within the closure specified in the second argument. The following lines show a new version of the previous code that adds the line with the print
statement. The code file for the sample is included in the swift_3_oop_chapter_07_28
folder:
let highestScoreSum2 = gameRepository.getAll().map({ $0.highestScore }).reduce(0, { sum, highestScore in print("sum value: (sum), highestScore value: (highestScore)") return sum + highestScore }) print(highestScoreSum2)
The following lines show the results for the previous line, where we can see how the sum value starts with the initial value specified in the initial
argument for the reduce
method and accumulates the sum completed so far. Finally, the highestScoreSum2
variable holds the sum of all the highestScore
values, that is, the last value of sum
, 85,912,770
plus the last highestScore
value, 10,572,340
. The result is 96,485,110
:
sum value: 0, highestScore value: 1050 sum value: 1050, highestScore value: 3741050 sum value: 3742100, highestScore value: 67881050 sum value: 71623150, highestScore value: 10025 sum value: 71633175, highestScore value: 1450708 sum value: 73083883, highestScore value: 1050320 sum value: 74134203, highestScore value: 6705203 sum value: 80839406, highestScore value: 4023134 sum value: 84862540, highestScore value: 1050230 sum value: 85912770, highestScore value: 10572340 96485110
The following screenshot shows the results of executing the previous lines in the Playground:
In the previous code, we had to pass a closure expression to the reduce
method as the method's final argument, and the closure expression is long. We can write it as a trailing closure, that is, a closure expression written after the closing parenthesis of the method call and outside it. The following lines show a new version of the previous code that uses a trailing closure. Note that the call to reduce
seems to include just one argument: 0
. However, the code included within curly braces after the method call is the combine argument for reduce
. Take a look at the following lines. The code file for the sample is included in the swift_3_oop_chapter_07_29
folder:
let highestScoreSum3 = gameRepository.getAll().map({ $0.highestScore }).reduce(0) { sum, highestScore in print("sum value: (sum), highestScore value: (highestScore)") return sum + highestScore }
3.145.45.5