The document discusses functional programming in Swift, highlighting its benefits such as maintainable code, ease of testing, and support for concurrency. Key concepts include immutable data, pure functions, higher-order functions, and functional tools like map, reduce, and filter. It also explores the integration of functional programming within Cocoa applications through an 'imperative shell' approach.
Functional Programming
⢠Aprogramming paradigm that treats computations
as the evaluation of mathematical functions and
avoids changing-state and mutable data. It is
declarative programming paradigm, which means
programming is done with expressions.
Immutable Values benefits
â˘Values canât change unexpectedly
⢠Can be shared without worrying
⢠Thread safe - Values play well with observers
10.
Example
let firstName ="Saugat"
let lastName = âGautam"
var middleName = "Kumar"
let numbers = Array(1âŚ10)
firstName.append("D") // Compiler Error
middleName.append("atunga") // All good
//âââââââââââââââââââââââââââââââââââââ
struct PersonalInfo {
var firstName: String
var lastName: String
var middleName: String
}
let emp1 = PersonalInfo(firstName: "Saugat", lastName: "Gautam", middleName:
11.
More Benefits
⢠TheValue of Values - Rich Hickey
http://www.infoq.com/presentations/Value-Values
⢠Controlling Complexity in Swift or Making Friends
with Value- Andy Matuschak
http://realm.io/news/andy-matuschak-controlling-
complexity/
http://www.objc.io/issue-16/swift-classes-vs-
structs.html
Pure Functions
⢠Sameinput always results in same output
(Referential Transparency)
⢠Evaluation of result does not cause any side effect
⢠eg. No change in database or to I/O devices
⢠Result value need not depend on all arguments but
it must depend on nothing other than the arguments
Not Pure!!
func naturalSum(numbers:[Int])-> Int{
var total = 0
for num in numbers {
total = total + num
}
return total
}
func sayHelloTo(name: String) {
println("Hello (name)")
}
Function as Parameter
funcaverage(x: Int, y: Int, f:(Int -> Int)) -> Int{
return (f(x) + f(y))/2
}
let square = {(x: Int) -> Int in return x * x}
average(2, 3, f:square)
24.
Function as Parameter
funcaverage(x: Int, y: Int, f:(Int -> Int) = {x in return x}) -> Int{
return (f(x) + f(y))/2
}
let square = {(x: Int) -> Int in return x * x}
average(2, 3, f:square)
25.
Function as Return
Value
funcadd(a: Int) -> (Int -> Int) {
return {b in a + b}
}
// partial application
let addThree = add(3)
//
let x3 = xs2.map(addThree)
Functional Toolbox
⢠Functors,Applicative Functors
⢠Monads
References:
Functional Programming in Swift
http://www.objc.io/books/
Why is a Monad like a writing desk?
http:www.infoq.com/presentations/Why-is-a-Monad-Like-a-Writing-Desk
Benefits of Functional
Approach
â˘Declarative. States what we want to do. Not how we
want to do it.
⢠Separates the mechanism(step through and select
each item) from the transformation logic
Filter
⢠Transforms theinitial collection to some final
collection applying some condition
⢠Final size may not be equal to initial size
38.
Filter Example forArray<T>
⢠Requirement:
⢠Produce a list of even squares of the first 10
positive numbers.
39.
Imperative Approach:
let firstTenPositiveIntegers= [Int](1...10)
var evenSquaresInFirstTen = [Int]()
for number in firstTenPositiveIntegers {
let square = number * number
if (square % 2) == 0 {
evenSquaresInFirstTen.append(square)
}
}
println(evenSquaresInFirstTen)
// [4, 16, 36, 64, 100]
40.
Functional Approach
let firstTenPositiveIntegers= [Int](1âŚ10)
let evenSquaresInFirstTen = firstTenPositiveIntegers.map({$0 * $0}).filter({($0%2) == 0})
println(evenSquaresInFirstTen)
// [4, 16, 36, 64, 100]
Imperative Approach
let firstTenPositiveIntegers= [Int](1âŚ10)
var sumOfEvenSquaresInFirstTen = 0
for number in firstTenPositiveIntegers {
let square = number * number
if (square % 2) == 0 {
sumOfEvenSquaresInFirstTen += square
}
}
println(sumOfEvenSquaresInFirstTen)
// 220
Currying
⢠Translating theevaluation of a function that takes
multiple arguments into evaluating a sequence of
functions each with a single argument(partial
application)
49.
Currying example
⢠Saywe have a method that takes two inputs and
add them
func add(a: Int, b: Int) -> Int {
return a + b
}
let sum = add(2, 3) // sum = 5
50.
Currying Example
⢠Nowwe want to add 2 to a list of numbers
⢠Drawbacks
⢠creating a closure just for passing add with default
value
⢠difficulty arises in case multiple default values are
needed
let xs = 1...100
let x = xs.map { add($0, 2) } // x = [3, 4, 5, 6, etc]
51.
Currying Example
⢠Usecurrying
⢠Drawbacks
⢠need of wrapper functions for each integer
func addTwo(a: Int) -> Int {
return add(a, 2)
}
let xs = 1...100
let x = xs2.map(addTwo)
52.
Currying Example
⢠Useanother currying method
func add(a: Int) -> (Int -> Int) {
return {b in a + b}
}
// Using method as a whole;
add(2)(3)
// partial application
let addThree = add(3)
//
let x3 = xs2.map(addThree)
Functional Core /Imperative
Shell
⢠Place applicationâs core data and logic in immutable
constructs (value types).
⢠Push state out to the âedgesâ. Represent state as
objects with mutable references to immutable core
constructs.
57.
Benefits
⢠Allows isolatedtesting
⢠Leads to an imperative shell with few conditionals,
making reasoning about the programâs state over
time much easier
58.
UI - CanWe Functionalize
the Imperative Shell?
⢠Not quite there.
Some references worth mentioning.
⢠Reactive Cocoa
https://github.com/ReactiveCocoa/ReactiveCocoa
⢠React Native
http://www.reactnative.com
⢠Functional View Controllers
http://chris.eidhof.nl/posts/functinal-view-controllers.html