This slide contains short introduction to different elements of functional programming along with some specific techniques with which we use functional programming in Swift.
3. Functional Programming
• A programming 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.
9. 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
• The Value 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
15. Swift Value Types vs
Reference Types
• Value Types:
• Numbers, strings, arrays, dictionaries, enums, tuples, and
structs.
• Reference Types:
• Classes
16. Value Types
• Single owner
• Copied on assign
• Example
var a = 10
var b = a
// a = 10, b = 5
b = 5
// a = 10, b = 5
17. Reference Types
• Multiple owners
• Shared on assignment
var a = UIView()
var b = a
// a.alpha = 1, b.alpha = 1
b.alpha = 0
// a.alpha = 0; b.alpha = 0
19. Pure Functions
• Same input 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
21. 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)")
}
23. Function as Parameter
func average(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
func average(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
func add(a: Int) -> (Int -> Int) {
return {b in a + b}
}
// partial application
let addThree = add(3)
//
let x3 = xs2.map(addThree)
28. 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
35. 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
37. Filter
• Transforms the initial collection to some final
collection applying some condition
• Final size may not be equal to initial size
38. Filter Example for Array<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]
44. 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
48. Currying
• Translating the evaluation of a function that takes
multiple arguments into evaluating a sequence of
functions each with a single argument(partial
application)
49. Currying example
• Say we 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
• Now we 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
• Use currying
• 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
• Use another 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)
56. 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 isolated testing
• Leads to an imperative shell with few conditionals,
making reasoning about the program’s state over
time much easier
58. UI - Can We 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