Map, Reduce
and Filter
in Swift
Aleksandras Smirnovas, coder.lt
Cocoa.lt #2, 2015
Agenda
• What is functional programming?
• Swift 101
• Examples of unfunctional to functional code
Functional Programming
is a programming paradigm—a style of building the
structure and elements of computer programs—that
treats computation as the evaluation of mathematical
functions and avoids changing-state and mutable
data.
http://en.wikipedia.org/wiki/Functional_programming
Functional Languages
• Haskell
• Skala
• F#
• Erlang
• Clojure
Key concepts
• First-class and higher-order functions
• Pure functions
• Recursion
• Functional programming in non-functional
languages
http://en.wikipedia.org/wiki/Functional_programming
Swift 101: Function types
func sum(x: Int, y: Int) -> (Int) {
return x + y
}
Swift 101: Function types
(Int, Int) -> (Int)
Swift 101: Passing and
returning functions
func calculator () -> ((Int, Int) -> Int) {
func sum(x: Int, y: Int) -> (Int) {
return x + y
}
return sum
}
let sum = calculator()
sum(5, 6)
Swift 101: Closure {()->() in}
{ (params) -> returnType in
statements
}
Basic F-programming toolkit
• map
• reduce
• filter
Map
func map<U>(transform: T -> U) -> Array<U>
Return an Array containing the results of calling
`transform(x)` on each element x of self
Map on collections
let list = ["c", "d", "a", "b"]
var uppercasedList = [String]()
for char in list {
uppercasedList.append(char.uppercaseString)
}
Map on collections
let list = ["c", "d", "a", "b"]
let uppercasedList = list.map ({
(char: String) -> String in
char.uppercaseString
})
Map on collections
let list = ["c", "d", "a", "b"]
let uppercasedList = list.map
({$0.uppercaseString})
Map on collections
let list = ["c", "d", "a", "b"]
let uppercasedList = list.map
{$0.uppercaseString}
FlatMap
func flatMap(transform: T -> [U]) ->[U]
Return an Array containing the results of calling
`transform(x)` on each element x of flattening self
FlatMap
let multiList = [["c", "d"], ["a"], ["b"]]
var uppercasedMultiList = multiList
.flatMap{ $0 }
.map {$0.uppercaseString}
Map on optionals
func increment(oNumber: Int?) -> Int? {
if let number = oNumber {
return number + 1
} else {
return nil
}
}
increment(10) //11
increment(nil) // nil
Map on optionals
func increment(oNumber: Int?) -> Int? {
return oNumber.map { number in number + 1 }
}
increment(10) //11
increment(nil) // nil
Map on optionals
func increment(oNumber: Int?) -> Int? {
return oNumber.map { $0 + 1 }
}
increment(10) //11
increment(nil) // nil
Reduce
func reduce(initial: U, combine: (U, T) -> U)
-> U
Return the result of repeatedly calling `combine` with
an accumulated value initialised to `initial` and each
element of self
Reduce
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
var sum = 0
for i in numbers {
sum += i
}
Reduce
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let sum = numbers.reduce(0, combine: {
(total, number) in
return total + number
})
Reduce
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let sum = numbers.reduce(0) {
(total, number) in
return total + number
}
Reduce
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let sum = numbers.reduce(0) {
(total, number) in
total + number
}
Reduce
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let sum = numbers.reduce(0) { $0 + $1 }
Reduce
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let sum = numbers.reduce(0, +}
Filter
func filter(includeElement: T -> Bool)
-> [T]
Return an Array containing the elements x of self for
which `includeElement(x)` is true
Filter
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let evenNumbers = numbers
.filter { $0 % 2 == 0 }
Map Filter reduce
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let iEvenSum = numbers
.map { $0 + 1 }
.filter { $0 % 2 == 0 }
.reduce(0, +)
Further Topics
• Function Composition
• Custom operators
• Curried functions
• Functors, Applicative Functors, and Monads
Further Topics
typealias Filter = CIImage -> CIImage
infix operator >>> { associativity left }
func >>> (filter1: Filter, filter2: Filter) -> Filter {
return {img in filter2(filter1(img))}
}
let myFilter = blur(blurRadius) >>> colorOverlay(overlayColor)
let result = myFilter(image)
http://www.objc.io/books/
Resources
• http://www.functionalvilnius.lt
• http://www.haskell.org/haskellwiki/Haskell
• http://learnyouahaskell.com
• http://www.objc.io/books/
• https://github.com/typelift/Swiftz
Thank you
Questions?

@saleksandras

Map, Reduce and Filter in Swift

  • 1.
    Map, Reduce and Filter inSwift Aleksandras Smirnovas, coder.lt Cocoa.lt #2, 2015
  • 2.
    Agenda • What isfunctional programming? • Swift 101 • Examples of unfunctional to functional code
  • 3.
    Functional Programming is aprogramming paradigm—a style of building the structure and elements of computer programs—that treats computation as the evaluation of mathematical functions and avoids changing-state and mutable data. http://en.wikipedia.org/wiki/Functional_programming
  • 4.
    Functional Languages • Haskell •Skala • F# • Erlang • Clojure
  • 5.
    Key concepts • First-classand higher-order functions • Pure functions • Recursion • Functional programming in non-functional languages http://en.wikipedia.org/wiki/Functional_programming
  • 6.
    Swift 101: Functiontypes func sum(x: Int, y: Int) -> (Int) { return x + y }
  • 7.
    Swift 101: Functiontypes (Int, Int) -> (Int)
  • 8.
    Swift 101: Passingand returning functions func calculator () -> ((Int, Int) -> Int) { func sum(x: Int, y: Int) -> (Int) { return x + y } return sum } let sum = calculator() sum(5, 6)
  • 9.
    Swift 101: Closure{()->() in} { (params) -> returnType in statements }
  • 10.
    Basic F-programming toolkit •map • reduce • filter
  • 11.
    Map func map<U>(transform: T-> U) -> Array<U> Return an Array containing the results of calling `transform(x)` on each element x of self
  • 12.
    Map on collections letlist = ["c", "d", "a", "b"] var uppercasedList = [String]() for char in list { uppercasedList.append(char.uppercaseString) }
  • 13.
    Map on collections letlist = ["c", "d", "a", "b"] let uppercasedList = list.map ({ (char: String) -> String in char.uppercaseString })
  • 14.
    Map on collections letlist = ["c", "d", "a", "b"] let uppercasedList = list.map ({$0.uppercaseString})
  • 15.
    Map on collections letlist = ["c", "d", "a", "b"] let uppercasedList = list.map {$0.uppercaseString}
  • 16.
    FlatMap func flatMap(transform: T-> [U]) ->[U] Return an Array containing the results of calling `transform(x)` on each element x of flattening self
  • 17.
    FlatMap let multiList =[["c", "d"], ["a"], ["b"]] var uppercasedMultiList = multiList .flatMap{ $0 } .map {$0.uppercaseString}
  • 18.
    Map on optionals funcincrement(oNumber: Int?) -> Int? { if let number = oNumber { return number + 1 } else { return nil } } increment(10) //11 increment(nil) // nil
  • 19.
    Map on optionals funcincrement(oNumber: Int?) -> Int? { return oNumber.map { number in number + 1 } } increment(10) //11 increment(nil) // nil
  • 20.
    Map on optionals funcincrement(oNumber: Int?) -> Int? { return oNumber.map { $0 + 1 } } increment(10) //11 increment(nil) // nil
  • 21.
    Reduce func reduce(initial: U,combine: (U, T) -> U) -> U Return the result of repeatedly calling `combine` with an accumulated value initialised to `initial` and each element of self
  • 22.
    Reduce let numbers =[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] var sum = 0 for i in numbers { sum += i }
  • 23.
    Reduce let numbers =[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] let sum = numbers.reduce(0, combine: { (total, number) in return total + number })
  • 24.
    Reduce let numbers =[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] let sum = numbers.reduce(0) { (total, number) in return total + number }
  • 25.
    Reduce let numbers =[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] let sum = numbers.reduce(0) { (total, number) in total + number }
  • 26.
    Reduce let numbers =[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] let sum = numbers.reduce(0) { $0 + $1 }
  • 27.
    Reduce let numbers =[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] let sum = numbers.reduce(0, +}
  • 28.
    Filter func filter(includeElement: T-> Bool) -> [T] Return an Array containing the elements x of self for which `includeElement(x)` is true
  • 29.
    Filter let numbers =[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] let evenNumbers = numbers .filter { $0 % 2 == 0 }
  • 30.
    Map Filter reduce letnumbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] let iEvenSum = numbers .map { $0 + 1 } .filter { $0 % 2 == 0 } .reduce(0, +)
  • 31.
    Further Topics • FunctionComposition • Custom operators • Curried functions • Functors, Applicative Functors, and Monads
  • 32.
    Further Topics typealias Filter= CIImage -> CIImage infix operator >>> { associativity left } func >>> (filter1: Filter, filter2: Filter) -> Filter { return {img in filter2(filter1(img))} } let myFilter = blur(blurRadius) >>> colorOverlay(overlayColor) let result = myFilter(image) http://www.objc.io/books/
  • 33.
    Resources • http://www.functionalvilnius.lt • http://www.haskell.org/haskellwiki/Haskell •http://learnyouahaskell.com • http://www.objc.io/books/ • https://github.com/typelift/Swiftz
  • 34.