Created
March 1, 2016 11:00
-
-
Save miguelfermin/8f04f223558a8ece92e7 to your computer and use it in GitHub Desktop.
Swift Functional Programming: Reduce
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Swift Functional Programming: Reduce | |
// | |
// By Miguel Fermin on 2016.01.28 | |
// | |
// Reference: http://www.raywenderlich.com/82599/swift-functional-programming-tutorial | |
import UIKit | |
// Manual Reduction: | |
// Take the even numbers between 1 and 10 and compute their sum. | |
// This calls for what is known as a reduce function, which takes a set of inputs and generates a single output. | |
var evens = [Int]() | |
for i in 1...10 { | |
if i % 2 == 0 { | |
evens.append(i) | |
} | |
} | |
var evenSum = 0 | |
for i in evens { | |
evenSum += i | |
} | |
evenSum | |
// Functional Reduction: | |
var evenSum2 = Array(1...10).filter { $0 % 2 == 0 }.reduce(0) { $0 + $1 } | |
evenSum2 | |
// 'filter' was covered in the "Filter" Playground. | |
// 'reduce' is an Array method that executes a function once for each element, accumulating the results. | |
// | |
// To understand how reduce works, it helps to look at its signature: | |
// | |
// func reduce<U>(initial: U, combine: (U, T) -> U) -> U | |
// | |
// The first parameter is the initial value, which is of type U. | |
// | |
// The second argument is the combine function that is executed once for each element of the array. | |
// | |
// 'combine' takes two arguments: | |
// the first, of type U, is the result of the previous invocation of combine; | |
// the second is the value of the array element that is being combined. | |
// | |
// The result returned by reduce is the value returned by the last combine invocation. | |
// | |
// | |
// The following table shows the step-by-step process of calling: | |
// | |
// ".reduce(0) { $0 + $1 }" | |
// | |
// Where: | |
// 0 is the initial value | |
// $0 is total: U | |
// $1 is number: T | |
// | |
// Test array = [2, 4, 6, 8, 10] | |
// | |
// - - - - - -|- - - - - - - - - - - - - - - -|- - - - - - - - | |
// | 'combine' | | |
// - - - - - -|- - - - - - - -|- - - - - - - -|- - - - - - - - | |
// Iteration | total: U | number: T | result | |
// - - - - - -|- - - - - - - -|- - - - - - - -|- - - - - - - - | |
// 1 | 0 | 2 | 2 | |
// - - - - - -|- - - - - - - -|- - - - - - - -|- - - - - - - - | |
// 2 | 2 | 4 | 6 | |
// - - - - - -|- - - - - - - -|- - - - - - - -|- - - - - - - - | |
// 3 | 6 | 6 | 12 | |
// - - - - - -|- - - - - - - -|- - - - - - - -|- - - - - - - - | |
// 4 | 12 | 8 | 20 | |
// - - - - - -|- - - - - - - -|- - - - - - - -|- - - - - - - - | |
// 5 | 20 | 10 | 30 | |
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
// Use cases: | |
// Reduces an array of integers into a string containing the numbers | |
let nums1 = Array(1...10).reduce("numbers: ") {(total, number) in total + "\(number) "} // regular syntax | |
let nums2 = Array(1...10).reduce("numbers: ") {$0 + "\($1) "} // short-hand syntax | |
// Use reduce to take an array of digits and convert them into an integer: | |
let digits = ["3", "1", "4", "1"] | |
// imperative approach | |
var digit = "" | |
for d in digits { digit += d } | |
Int(digit) | |
// functional approach (reduce) | |
let myInt = Int(digits.reduce("") {$0 + $1} ) | |
myInt | |
/* The Magic Behind Reduce */ | |
extension Array { | |
func myReduce<U, T>(seed: U, combiner: (U, T) -> U) -> U { | |
var current = seed | |
for item in self { | |
current = combiner(current, item as! T) | |
} | |
return current | |
} | |
} | |
/* The above adds a myReduce method to Array that mimics the built-in reduce function. | |
* This method simply iterates over each item in the array, invoking combiner at each step. | |
* | |
* At this point, you might be thinking, “Why would I want to implement filter or reduce myself?” | |
* The answer is, “You probably wouldn’t!” | |
* | |
* However, you might want to expand your use of the functional paradigm in Swift and implement your own functional methods. | |
* It’s encouraging (and important!) to see and understand just how easy it is to implement powerful methods like reduce. | |
*/ | |
let myInt2 = Int(digits.myReduce("") { $0 + $1 }) | |
myInt2 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment