THE FUNCTIONAL 
WAY 
@NATASHATHEROBOT
"functional programming is a 
programming paradigm... that treats 
computation as the evaluation of 
mathematical functions and avoids 
changing-state and mutable data." 
Wikipedia
"A mathematical function is a function 
that when you give it the same 
argument, it will give you the same 
result" - Edx FP101x
▸ computation as the evaluation of mathematical functions 
▸ avoid changing state 
▸ avoid mutable data
NO SIDE EFFECTS
let numbers = Array(1...10) 
var total = 0 
func addNumbers() { 
for number in numbers { 
total += number 
} 
}
addNumbers() 
total // 55 
addNumbers() 
total // 110 
addNumbers() 
total // 165
let myNumbers = Array(1...10) 
var total = addNumbers(myNumbers) 
func addNumbers(numbers: [Int]) -> Int { 
// can also be written shorthand as 
// numbers.reduce(0,+) 
return numbers.reduce(0) { (sum, number) in sum + number } 
}
total = addNumbers(myNumbers) // 55 
total = addNumbers(myNumbers) // 55 
total = addNumbers(myNumbers) // 55
import Foundation 
class Gift { 
let recipient: String 
let item: String 
let budget: NSDecimalNumber 
let status: Status 
enum Status: String { 
case Purchased = "Purchased" 
case Wrapped = "Wrapped" 
case Delivered = "Delivered" 
} 
init(recipient: String, 
item: String, 
budget: NSDecimalNumber, 
status: Status) 
{ 
self.recipient = recipient 
self.item = item 
self.budget = budget 
self.status = status 
} 
}
extension Gift { 
func todo() -> String { 
switch status { 
case .Purchased: 
return "Wrap it!" 
case .Wrapped: 
return "Mail it!" 
case .Delivered: 
return "Relax and drink some eggnog :)" 
} 
} 
}
extension Gift { 
func todo(fromStatus status: Status) -> String { 
switch status { 
case .Purchased: 
return "Wrap it!" 
case .Wrapped: 
return "Mail it!" 
case .Delivered: 
return "Relax and drink some eggnog :)" 
} 
} 
}
class GiftTests: XCTestCase { 
func testTodo_Purchased() { 
let gift = Gift( 
recipient: "My Cousin Julie, 
item: "GoldieBlox", 
budget: NSDecimalNumber(double: 20.00), 
status: .Purchased) 
XCTAssertEqual(gift.todo(), "Wrap it!") 
} 
func testTodo_Wrapped() { 
let gift = Gift( 
recipient: "My Cousin Julie", 
item: "GoldieBlox", 
budget: NSDecimalNumber(double: 20.00), 
status: .Wrapped) 
XCTAssertEqual(gift.todo(), "Mail it!") 
} 
func testTodo_Delivered() { 
let gift = Gift( 
recipient: "My Cousin Julie", 
item: "GoldieBlox", 
budget: NSDecimalNumber(double: 20.00), 
status: .Delivered) 
XCTAssertEqual(gift.todo(), "Relax and drink some eggnog :)") 
} 
}
import XCTest 
class GiftTests: XCTestCase { 
let gift = Gift( 
recipient: "My Cousin Tommy", 
item: "Choo Choo Train", 
budget: NSDecimalNumber(double: 20.00), 
status: .Purchased) 
func testTodo_Purchased() { 
XCTAssertEqual(gift.todo(fromStatus: .Purchased), "Wrap it!") 
} 
func testTodo_Wrapped() { 
XCTAssertEqual(gift.todo(fromStatus: .Wrapped), "Mail it!") 
} 
func testTodo_Delivered() { 
XCTAssertEqual(gift.todo(fromStatus: .Delivered), "Relax and drink some eggnog :)") 
} 
}
import XCTest 
class GiftTests: XCTestCase { 
func testTodo_Purchased() { 
XCTAssertEqual(Gift.todo(fromStatus: .Purchased), "Wrap it!") 
} 
func testTodo_Wrapped() { 
XCTAssertEqual(Gift.todo(fromStatus: .Wrapped), "Mail it!") 
} 
func testTodo_Delivered() { 
XCTAssertEqual(Gift.todo(fromStatus: .Delivered), "Relax and drink some eggnog :)") 
} 
}
VALUE TYPES
"Almost all types in Swift are value 
types, including arrays, dictionaries, 
numbers, booleans, tuples, and enums. 
Classes are the exception rather than 
the rule." - Functional Swift Book
NSError *err = nil; 
CGFloat result = [MYArithmetic divide:2.5 by:3.0 error:&err]; 
if (err) { 
NSLog(@"%@", err) 
} else { 
[MYArithmetic doSomethingWithResult:result] 
} 
@nomothetis
enum Result { 
case Success(AnyObject) 
case Failure(NSError) 
} 
@nomothetis
let result = MYArithmetic.divide(2.5, by:3) 
switch result { 
case Success(let quotient): 
doSomethingWithResult(quotient) 
case Failure(let error): 
handleError(error) 
} 
@nomothetis
http://nomothetis.svbtle.com/error-handling-in-swift
CURRYING
func add(x: Int, y: Int) -> Int { 
return x + y 
} 
add(2, 3) // 5
func add(x: Int) -> Int -> Int { 
return { y in return x + y } 
} 
let partialAdd = add(2) 
// let addFunc: (Int -> Int) 
let sum = partialAdd(3) 
// 5 
let arr = [1,2,3] 
let incrementBy2 = arr.map(partialAdd) 
// [3,4,5] 
add(6)(4) 
// 10
func add(#x: Int)(y: Int) -> Int { 
return x + y 
} 
add(x: 2)(y: 3) 
// 5
struct Logger { 
/// Level of log message to aid in the filtering of logs 
enum Level: Int, Printable { 
/// Messages intended only for debug mode 
case Debug = 3 
/// Messages intended to warn of potential errors 
case Warn = 2 
/// Critical error messages 
case Error = 1 
/// Log level to turn off all logging 
case None = 0 
var description: String { 
switch(self) { 
case .Debug: 
return "Debug" 
case .Warn: 
return "Warning" 
case .Error: 
return "Error" 
case .None: 
return "" 
} 
} 
} 
} 
@drewag
extension Logger { 
/// What is the max level to be logged 
/// 
/// Any logs under the given log level will be ignored 
static var logLevel: Level = .Warn 
/// Log a message to the console 
static func log 
(#level: Level) 
(name: String) 
(message: String) -> String 
{ 
if level.rawValue <= Logger.logLevel.rawValue { 
return "(level.description): (name) - (message)" 
} 
return "" 
} 
} 
@drewag
Logger.log(level: .Debug)(name: "MyFunction")(message: "Is this being called?") 
// Debug: MyFunction - Is this being called?
extension Logger { 
/// Logger for debug messages 
static var debug = Logger.log(level: .Debug) 
// static var debug: (name: String) -> (message: String) -> String 
/// Logger for warnings 
static var warn = Logger.log(level: .Warn) 
/// Logger for errors 
static var error = Logger.log(level: .Error) 
} 
@drewag
Logger.logLevel = .Debug 
func myFunctionToDebug() { 
var x = 5 
// do something to x 
Logger.debug(name: "myFunctionToDebug")(message: "x: (x)") 
} 
myFunctionToDebug() 
// Prints: "Debug: myFunctionToDebug - x: 10" 
@drewag
func myFunctionToDebug() { 
var x = 5 
var y = 3 
// do something to x 
// do something to y 
let debugMyFunction = Logger.debug(name: "myFunctionToDebug") 
debugMyFunction(message: "x: (x)") 
debugMyFunction(message: "y: (y)") 
} 
myFunctionToDebug() 
// Prints: "Debug: myFunctionToDebug - x: 10" 
// Prints: "Debug: myFunctionToDebug - y: 13"
http://drewag.me/posts/practical-use-for-curried-functions-in-swift
TYPE-DRIVEN 
DESIGN
func credits(account: Account) -> Int { 
// ask data source for account credits 
return credits 
} 
@FunctionalSwift
typealias Credits = Int 
func credits(account: Account) -> Credits { 
// ask data source for amount of credits 
return amount 
} 
@FunctionalSwift
"One important lesson I've learned is 
that designing the right types for your 
problem is a great way to help the 
compiler debug your program." - 
@wouterswierstra
struct Credits { let amount: Int } 
func credits(account: Account) -> Credits { 
// ask data source for amount of credits 
return Credits(amount: amount) 
} 
@FunctionalSwift
let myCredits = credits(myAccount) 
myCredits + 1 // ERROR 
// Cannot invoke '+' with an argument of type 
// '(Credit, IntegerLiteralConvertable)'
http://www.objc.io/snippets/8.html 
http://www.swiftcast.tv/articles/the-design-of-types
RESOURCES 
▸ Functional Swift Book 
▸ Edx FP101x 
▸ Functional Snippets 
▸ An Introduction to Haskell - Skills Matter 
▸ swiftnews.curated.co
QUESTIONS? 
@NATASHATHEROBOT

Funcitonal Swift Conference: The Functional Way

  • 1.
    THE FUNCTIONAL WAY @NATASHATHEROBOT
  • 2.
    "functional programming isa programming paradigm... that treats computation as the evaluation of mathematical functions and avoids changing-state and mutable data." Wikipedia
  • 3.
    "A mathematical functionis a function that when you give it the same argument, it will give you the same result" - Edx FP101x
  • 4.
    ▸ computation asthe evaluation of mathematical functions ▸ avoid changing state ▸ avoid mutable data
  • 6.
  • 7.
    let numbers =Array(1...10) var total = 0 func addNumbers() { for number in numbers { total += number } }
  • 8.
    addNumbers() total //55 addNumbers() total // 110 addNumbers() total // 165
  • 9.
    let myNumbers =Array(1...10) var total = addNumbers(myNumbers) func addNumbers(numbers: [Int]) -> Int { // can also be written shorthand as // numbers.reduce(0,+) return numbers.reduce(0) { (sum, number) in sum + number } }
  • 10.
    total = addNumbers(myNumbers)// 55 total = addNumbers(myNumbers) // 55 total = addNumbers(myNumbers) // 55
  • 11.
    import Foundation classGift { let recipient: String let item: String let budget: NSDecimalNumber let status: Status enum Status: String { case Purchased = "Purchased" case Wrapped = "Wrapped" case Delivered = "Delivered" } init(recipient: String, item: String, budget: NSDecimalNumber, status: Status) { self.recipient = recipient self.item = item self.budget = budget self.status = status } }
  • 12.
    extension Gift { func todo() -> String { switch status { case .Purchased: return "Wrap it!" case .Wrapped: return "Mail it!" case .Delivered: return "Relax and drink some eggnog :)" } } }
  • 13.
    extension Gift { func todo(fromStatus status: Status) -> String { switch status { case .Purchased: return "Wrap it!" case .Wrapped: return "Mail it!" case .Delivered: return "Relax and drink some eggnog :)" } } }
  • 14.
    class GiftTests: XCTestCase{ func testTodo_Purchased() { let gift = Gift( recipient: "My Cousin Julie, item: "GoldieBlox", budget: NSDecimalNumber(double: 20.00), status: .Purchased) XCTAssertEqual(gift.todo(), "Wrap it!") } func testTodo_Wrapped() { let gift = Gift( recipient: "My Cousin Julie", item: "GoldieBlox", budget: NSDecimalNumber(double: 20.00), status: .Wrapped) XCTAssertEqual(gift.todo(), "Mail it!") } func testTodo_Delivered() { let gift = Gift( recipient: "My Cousin Julie", item: "GoldieBlox", budget: NSDecimalNumber(double: 20.00), status: .Delivered) XCTAssertEqual(gift.todo(), "Relax and drink some eggnog :)") } }
  • 15.
    import XCTest classGiftTests: XCTestCase { let gift = Gift( recipient: "My Cousin Tommy", item: "Choo Choo Train", budget: NSDecimalNumber(double: 20.00), status: .Purchased) func testTodo_Purchased() { XCTAssertEqual(gift.todo(fromStatus: .Purchased), "Wrap it!") } func testTodo_Wrapped() { XCTAssertEqual(gift.todo(fromStatus: .Wrapped), "Mail it!") } func testTodo_Delivered() { XCTAssertEqual(gift.todo(fromStatus: .Delivered), "Relax and drink some eggnog :)") } }
  • 16.
    import XCTest classGiftTests: XCTestCase { func testTodo_Purchased() { XCTAssertEqual(Gift.todo(fromStatus: .Purchased), "Wrap it!") } func testTodo_Wrapped() { XCTAssertEqual(Gift.todo(fromStatus: .Wrapped), "Mail it!") } func testTodo_Delivered() { XCTAssertEqual(Gift.todo(fromStatus: .Delivered), "Relax and drink some eggnog :)") } }
  • 17.
  • 18.
    "Almost all typesin Swift are value types, including arrays, dictionaries, numbers, booleans, tuples, and enums. Classes are the exception rather than the rule." - Functional Swift Book
  • 19.
    NSError *err =nil; CGFloat result = [MYArithmetic divide:2.5 by:3.0 error:&err]; if (err) { NSLog(@"%@", err) } else { [MYArithmetic doSomethingWithResult:result] } @nomothetis
  • 20.
    enum Result { case Success(AnyObject) case Failure(NSError) } @nomothetis
  • 21.
    let result =MYArithmetic.divide(2.5, by:3) switch result { case Success(let quotient): doSomethingWithResult(quotient) case Failure(let error): handleError(error) } @nomothetis
  • 22.
  • 23.
  • 24.
    func add(x: Int,y: Int) -> Int { return x + y } add(2, 3) // 5
  • 25.
    func add(x: Int)-> Int -> Int { return { y in return x + y } } let partialAdd = add(2) // let addFunc: (Int -> Int) let sum = partialAdd(3) // 5 let arr = [1,2,3] let incrementBy2 = arr.map(partialAdd) // [3,4,5] add(6)(4) // 10
  • 26.
    func add(#x: Int)(y:Int) -> Int { return x + y } add(x: 2)(y: 3) // 5
  • 27.
    struct Logger { /// Level of log message to aid in the filtering of logs enum Level: Int, Printable { /// Messages intended only for debug mode case Debug = 3 /// Messages intended to warn of potential errors case Warn = 2 /// Critical error messages case Error = 1 /// Log level to turn off all logging case None = 0 var description: String { switch(self) { case .Debug: return "Debug" case .Warn: return "Warning" case .Error: return "Error" case .None: return "" } } } } @drewag
  • 28.
    extension Logger { /// What is the max level to be logged /// /// Any logs under the given log level will be ignored static var logLevel: Level = .Warn /// Log a message to the console static func log (#level: Level) (name: String) (message: String) -> String { if level.rawValue <= Logger.logLevel.rawValue { return "(level.description): (name) - (message)" } return "" } } @drewag
  • 29.
    Logger.log(level: .Debug)(name: "MyFunction")(message:"Is this being called?") // Debug: MyFunction - Is this being called?
  • 30.
    extension Logger { /// Logger for debug messages static var debug = Logger.log(level: .Debug) // static var debug: (name: String) -> (message: String) -> String /// Logger for warnings static var warn = Logger.log(level: .Warn) /// Logger for errors static var error = Logger.log(level: .Error) } @drewag
  • 31.
    Logger.logLevel = .Debug func myFunctionToDebug() { var x = 5 // do something to x Logger.debug(name: "myFunctionToDebug")(message: "x: (x)") } myFunctionToDebug() // Prints: "Debug: myFunctionToDebug - x: 10" @drewag
  • 32.
    func myFunctionToDebug() { var x = 5 var y = 3 // do something to x // do something to y let debugMyFunction = Logger.debug(name: "myFunctionToDebug") debugMyFunction(message: "x: (x)") debugMyFunction(message: "y: (y)") } myFunctionToDebug() // Prints: "Debug: myFunctionToDebug - x: 10" // Prints: "Debug: myFunctionToDebug - y: 13"
  • 33.
  • 34.
  • 35.
    func credits(account: Account)-> Int { // ask data source for account credits return credits } @FunctionalSwift
  • 36.
    typealias Credits =Int func credits(account: Account) -> Credits { // ask data source for amount of credits return amount } @FunctionalSwift
  • 37.
    "One important lessonI've learned is that designing the right types for your problem is a great way to help the compiler debug your program." - @wouterswierstra
  • 38.
    struct Credits {let amount: Int } func credits(account: Account) -> Credits { // ask data source for amount of credits return Credits(amount: amount) } @FunctionalSwift
  • 39.
    let myCredits =credits(myAccount) myCredits + 1 // ERROR // Cannot invoke '+' with an argument of type // '(Credit, IntegerLiteralConvertable)'
  • 40.
  • 41.
    RESOURCES ▸ FunctionalSwift Book ▸ Edx FP101x ▸ Functional Snippets ▸ An Introduction to Haskell - Skills Matter ▸ swiftnews.curated.co
  • 42.