Skip to content

Instantly share code, notes, and snippets.

@miguelfermin
Created March 1, 2016 11:00
Show Gist options
  • Save miguelfermin/8f04f223558a8ece92e7 to your computer and use it in GitHub Desktop.
Save miguelfermin/8f04f223558a8ece92e7 to your computer and use it in GitHub Desktop.
Swift Functional Programming: Reduce
// 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