SlideShare a Scribd company logo
1 of 103
Download to read offline
What Swift can teach us all!
or…
How Swift has opened our minds
What Swift can teach us all!
or…
How Swift has opened our minds
Let’s talk about functions!
Let’s talk about functions!
*pun intended
fun
Let’s talk about functions!
Did you know that in Swift you can assign functions to variables?
No, seriously…
*pun intended
fun
var number = 4 // A boring Int
Let’s talk about functions!
Did you know that in Swift you can assign functions to variables?
No, seriously…
*pun intended
fun
var number = 4 // A boring Int
Let’s talk about functions!
var sum = { (a: Float, b: Float) in
return a + b
}
Did you know that in Swift you can assign functions to variables?
No, seriously…
*pun intended
fun
var number = 4 // A boring Int
Let’s talk about functions!
var sum = { (a: Float, b: Float) in
return a + b
}
Did you know that in Swift you can assign functions to variables?
No, seriously…
*pun intended
fun
// A fun...ction
var number = 4 // A boring Int
Let’s talk about functions!
var sum = { (a: Float, b: Float) in
return a + b
}
Did you know that in Swift you can assign functions to variables?
No, seriously…
*pun intended
fun
// A fun...ction
var number = 4 // A boring Int
Let’s talk about functions!
var sum = { (a: Float, b: Float) in
return a + b
}
let four = sum(2, 2)
print(four) // Prints 4.0
Did you know that in Swift you can assign functions to variables?
No, seriously…
*pun intended
fun
// A fun...ction
Why the hell would I need that…?
Higher order functions
Higher order functions
Moment…
Higher order functions
Moment…
What’s that?
Higher order functions
Moment…
What’s that?
Roughly speaking…
"A higher order function is a function that accepts functions
as parameters"
- Some guy.
let sum = { (a: Float, b: Float) in
return a + b
}
let subtract = { (a: Float, b: Float) in
return a - b
}
let multiply = { (a: Float, b: Float) in
return a * b
}
let divide = { (a: Float, b: Float) in
return a / b
}
func main() {
let eight = operateOn(6, and: 2, usingFunction: sum)
let four = operateOn(6, and: 2, usingFunction: subtract)
let twelve = operateOn(6, and: 2, usingFunction: multiply)
let three = operateOn(6, and: 2, usingFunction: divide)
}
func operateOn(a: Float, and b: Float, usingFunction f: (Float, Float) -> Float)
-> Float {
return f(a, b)
}
let sum = { (a: Float, b: Float) in
return a + b
}
let subtract = { (a: Float, b: Float) in
return a - b
}
let multiply = { (a: Float, b: Float) in
return a * b
}
let divide = { (a: Float, b: Float) in
return a / b
}
func main() {
let eight = operateOn(6, and: 2, usingFunction: sum)
let four = operateOn(6, and: 2, usingFunction: subtract)
let twelve = operateOn(6, and: 2, usingFunction: multiply)
let three = operateOn(6, and: 2, usingFunction: divide)
}
func operateOn(a: Float, and b: Float, usingFunction f: (Float, Float) -> Float)
-> Float {
return f(a, b)
}
We have defined 4
functions
as variables.
let sum = { (a: Float, b: Float) in
return a + b
}
let subtract = { (a: Float, b: Float) in
return a - b
}
let multiply = { (a: Float, b: Float) in
return a * b
}
let divide = { (a: Float, b: Float) in
return a / b
}
func main() {
let eight = operateOn(6, and: 2, usingFunction: sum)
let four = operateOn(6, and: 2, usingFunction: subtract)
let twelve = operateOn(6, and: 2, usingFunction: multiply)
let three = operateOn(6, and: 2, usingFunction: divide)
}
func operateOn(a: Float, and b: Float, usingFunction f: (Float, Float) -> Float)
-> Float {
return f(a, b)
}
We have defined 4
functions
as variables.
We pass in those functions in the
operateOn call "as if" they
were variables… (well, they
actually are)
operateOn is a higher order function, because it
accepts a function as an input parameter.
let sum = { (a: Float, b: Float) in
return a + b
}
let subtract = { (a: Float, b: Float) in
return a - b
}
let multiply = { (a: Float, b: Float) in
return a * b
}
let divide = { (a: Float, b: Float) in
return a / b
}
func main() {
let eight = operateOn(6, and: 2, usingFunction: sum)
let four = operateOn(6, and: 2, usingFunction: subtract)
let twelve = operateOn(6, and: 2, usingFunction: multiply)
let three = operateOn(6, and: 2, usingFunction: divide)
}
func operateOn(a: Float, and b: Float, usingFunction f: (Float, Float) -> Float)
-> Float {
return f(a, b)
}
We have defined 4
functions
as variables.
We pass in those functions in the
operateOn call "as if" they
were variables… (well, they
actually are)
Still… Why the hell would I need
that???
Let’s see a more practical example…
func teenagersFromPeople(people: [Person]) -> [Person] {
var teenagers = [Person]()
for person in people {
if person.age > 12 && person.age < 20 {
teenagers.append(person)
}
}
return teenagers
}
Let’s see a more practical example…
func teenagersFromPeople(people: [Person]) -> [Person] {
var teenagers = [Person]()
for person in people {
if person.age > 12 && person.age < 20 {
teenagers.append(person)
}
}
return teenagers
}
Mutability
Let’s see a more practical example…
func teenagersFromPeople(people: [Person]) -> [Person] {
var teenagers = [Person]()
for person in people {
if person.age > 12 && person.age < 20 {
teenagers.append(person)
}
}
return teenagers
}
Mutability
Danger!
Let’s see a more practical example…
func teenagersFromPeople(people: [Person]) -> [Person] {
var teenagers = [Person]()
for person in people {
if person.age > 12 && person.age < 20 {
teenagers.append(person)
}
}
return teenagers
}
Mutability
Danger!
But… Hold on… Why?
Let’s see a more practical example…
Nope,
it’s not
this…
func teenagersFromPeople(people: [Person]) -> [Person] {
var teenagers = [Person]()
for person in people {
if person.age > 12 && person.age < 20 {
teenagers.append(person)
}
}
return teenagers
}
Mutability
Danger!
But… Hold on… Why?
Let’s see a more practical example…
Mutability:
By using mutable variables, we are not 100% sure what
the value of the variable at some point is.
It could be modified somewhere, and that leads to the
fact that we need to keep track of where that variable
is being used and how it’s being modified.
In smaller cases like this, it’s easy to keep track, but…
for jsonRow in rows {
var post = Post(json: jsonRow)
let postId = jsonRow["id"].stringValue
if let storedPost = realm.objects(Post).filter("id = %@", postId).first {
post = storedPost
post!.refresh(jsonRow, endpoint: self.basePath as! ServerEndpoint)
post!.postType = PostType(rawValue:(storedPost.postType.rawValue | feedType.rawValue))
updates.append(post!.id)
} else {
post = Post(json: jsonRow, endpoint: self.basePath as! ServerEndpoint)
post!.postType = feedType
additions.append(postId)
}
realm.add(post!, update: true)
}
How about this…?
for jsonRow in rows {
var post = Post(json: jsonRow)
let postId = jsonRow["id"].stringValue
if let storedPost = realm.objects(Post).filter("id = %@", postId).first {
post = storedPost
post!.refresh(jsonRow, endpoint: self.basePath as! ServerEndpoint)
post!.postType = PostType(rawValue:(storedPost.postType.rawValue | feedType.rawValue))
updates.append(post!.id)
} else {
post = Post(json: jsonRow, endpoint: self.basePath as! ServerEndpoint)
post!.postType = feedType
additions.append(postId)
}
realm.add(post!, update: true)
}
How about this…?
Let’s keep track of post…
for jsonRow in rows {
var post = Post(json: jsonRow)
let postId = jsonRow["id"].stringValue
if let storedPost = realm.objects(Post).filter("id = %@", postId).first {
post = storedPost
post!.refresh(jsonRow, endpoint: self.basePath as! ServerEndpoint)
post!.postType = PostType(rawValue:(storedPost.postType.rawValue | feedType.rawValue))
updates.append(post!.id)
} else {
post = Post(json: jsonRow, endpoint: self.basePath as! ServerEndpoint)
post!.postType = feedType
additions.append(postId)
}
realm.add(post!, update: true)
}
How about this…?
Let’s keep track of post…
for jsonRow in rows {
var post = Post(json: jsonRow)
let postId = jsonRow["id"].stringValue
if let storedPost = realm.objects(Post).filter("id = %@", postId).first {
post = storedPost
post!.refresh(jsonRow, endpoint: self.basePath as! ServerEndpoint)
post!.postType = PostType(rawValue:(storedPost.postType.rawValue | feedType.rawValue))
updates.append(post!.id)
} else {
post = Post(json: jsonRow, endpoint: self.basePath as! ServerEndpoint)
post!.postType = feedType
additions.append(postId)
}
realm.add(post!, update: true)
}
How about this…?
At this point, we can’t easily ensure what the post is going to be…
Let’s keep track of post…
func teenagersFromPeople(people: [Person]) -> [Person] {
var teenagers = [Person]()
for person in people {
if person.age > 12 && person.age < 20 {
teenagers.append(person)
}
}
return teenagers
}
Back to our example…
Could we replace it, somehow, such that we
avoid mutability?
func teenagersFromPeople(people: [Person]) -> [Person] {
let teenagers: [Person]
teenagers = people.filter({ (person) -> Bool in
return person.age > 12 && person.age < 20
})
return teenagers
}
Higher order functions to the rescue!
func teenagersFromPeople(people: [Person]) -> [Person] {
let teenagers: [Person]
teenagers = people.filter({ (person) -> Bool in
return person.age > 12 && person.age < 20
})
return teenagers
}
Higher order functions to the rescue!
// let :)
func teenagersFromPeople(people: [Person]) -> [Person] {
let teenagers: [Person]
teenagers = people.filter({ (person) -> Bool in
return person.age > 12 && person.age < 20
})
return teenagers
}
Higher order functions to the rescue!
// let 😊
func teenagersFromPeople(people: [Person]) -> [Person] {
let teenagers: [Person]
teenagers = people.filter({ (person) -> Bool in
return person.age > 12 && person.age < 20
})
return teenagers
}
Higher order functions to the rescue!
// let 😊
Yes, emojis are allowed in Swift source code… ✌
func teenagersFromPeople(people: [Person]) -> [Person] {
let teenagers: [Person]
teenagers = people.filter({ (person) -> Bool in
return person.age > 12 && person.age < 20
})
return teenagers
}
Higher order functions to the rescue!
// let 😊
Yes, we are tending to become hippies
Yes, emojis are allowed in Swift source code… ✌
func teenagersFromPeople(people: [Person]) -> [Person] {
let teenagers: [Person]
teenagers = people.filter({ (person) -> Bool in
return person.age > 12 && person.age < 20
})
return teenagers
}
Higher order functions to the rescue!
// let 😊
Yes, we are tending to become hippies
Yes, emojis are allowed in Swift source code… ✌
func teenagersFromPeople(people: [Person]) -> [Person] {
let teenagers: [Person]
teenagers = people.filter({ (person) -> Bool in
return person.age > 12 && person.age < 20
})
return teenagers
}
Higher order functions to the rescue!
// let 😊
Yes, we are tending to become hippies
Yes, emojis are allowed in Swift source code… ✌
If we could just simplify this…
func teenagersFromPeople(people: [Person]) -> [Person] {
let teenagers: [Person]
teenagers = people.filter { $0.age > 12 && $0.age < 20 }
return teenagers
}
Simplicity, oh, yeah…
func teenagersFromPeople(people: [Person]) -> [Person] {
return people.filter { $0.age > 12 && $0.age < 20 }
}
Even simpler, baby…
func teenagersFromPeople(people: [Person]) -> [Person] {
var teenagers = [Person]()
for person in people {
if person.age > 12 && person.age < 20 {
teenagers.append(person)
}
}
return teenagers
}
Not
preferred
Higher order functions
func teenagersFromPeople(people: [Person]) -> [Person] {
var teenagers = [Person]()
for person in people {
if person.age > 12 && person.age < 20 {
teenagers.append(person)
}
}
return teenagers
}
Not
preferred
func teenagersFromPeople(people: [Person]) -> [Person] {
return people.filter { $0.age > 12 && $0.age < 20 }
}
Preferred
Higher order functions
func teenagersFromPeople(people: [Person]) -> [Person] {
var teenagers = [Person]()
for person in people {
if person.age > 12 && person.age < 20 {
teenagers.append(person)
}
}
return teenagers
}
Not
preferred
func teenagersFromPeople(people: [Person]) -> [Person] {
return people.filter { $0.age > 12 && $0.age < 20 }
}
Preferred
FILTER
Higher order functions
func idsFromPeople(people: [Person]) -> [String] {
var ids = [String]()
for person in people {
ids.append(person.id)
}
return ids
}
Not
preferred
Higher order functions
func idsFromPeople(people: [Person]) -> [String] {
var ids = [String]()
for person in people {
ids.append(person.id)
}
return ids
}
func idsFromPeople(people: [Person]) -> [String] {
return people.map { $0.id }
}
Preferred
Not
preferred
Higher order functions
func idsFromPeople(people: [Person]) -> [String] {
var ids = [String]()
for person in people {
ids.append(person.id)
}
return ids
}
func idsFromPeople(people: [Person]) -> [String] {
return people.map { $0.id }
}
Preferred
Not
preferred
MAP
Higher order functions
func childrenCountFromPeople(people: [Person]) -> Int {
var count = 0
for person in people {
count += person.children.count
}
return count
}
Not
preferred
Higher order functions
func childrenCountFromPeople(people: [Person]) -> Int {
var count = 0
for person in people {
count += person.children.count
}
return count
}
func childrenCountFromPeople(people: [Person]) -> Int {
return people.reduce(0) { $0 + $1.children.count }
}
Preferred
Not
preferred
Higher order functions
func childrenCountFromPeople(people: [Person]) -> Int {
var count = 0
for person in people {
count += person.children.count
}
return count
}
func childrenCountFromPeople(people: [Person]) -> Int {
return people.reduce(0) { $0 + $1.children.count }
}
Preferred
Not
preferred
REDUCE
Higher order functions
FILTER
MAP
REDUCE
You want some of the original
elements
You want new elements based
on the original elements
You want a result based on the
original elements
Pure functions
Pure functions
A pure function is a function where the return value is only
determined by its input values, without observable side
effects.
Pure functions
A pure function is a function where the return value is only
determined by its input values, without observable side
effects.
• There is a return value
Pure functions
A pure function is a function where the return value is only
determined by its input values, without observable side
effects.
• There is a return value
• Result depends only on input values
Pure functions
A pure function is a function where the return value is only
determined by its input values, without observable side
effects.
• There is a return value
• No side effects
• Result depends only on input values
Pure functions
A pure function is a function where the return value is only
determined by its input values, without observable side
effects.
• There is a return value
• No side effects
• Result depends only on input values 100%
unit-testable!
• There is a return value
• No side effects
• Result depends only on input values
func configureLabelTextWithNumber(number: Int) {
self.numberLabel.text = "(number)"
}
Example #1
Pure functions
• There is a return value
• No side effects
• Result depends only on input values
func configureLabelTextWithNumber(number: Int) {
self.numberLabel.text = "(number)"
}
• There is a return value ❌
Example #1
Pure functions
• There is a return value
• No side effects
• Result depends only on input values
func configureLabelTextWithNumber(number: Int) {
self.numberLabel.text = "(number)"
}
• There is a return value ❌
• Result depends only on input values ✅
Example #1
Pure functions
• There is a return value
• No side effects
• Result depends only on input values
func configureLabelTextWithNumber(number: Int) {
self.numberLabel.text = "(number)"
}
• There is a return value ❌
• No side effects ❌
• Result depends only on input values ✅
Example #1
Pure functions
• There is a return value
• No side effects
• Result depends only on input values
func configureLabelTextWithNumber(number: Int) {
self.numberLabel.text = "(number)"
}
• There is a return value ❌
• No side effects ❌
• Result depends only on input values ✅
Example #1
Functions using "self.something" are a call to side effects
Pure functions
• There is a return value
• No side effects
• Result depends only on input values
func labelTextForNumber(number: Int) -> String {
return "(number)"
}
Example #1
Pure functions
• There is a return value
• No side effects
• Result depends only on input values
• There is a return value ✅
func labelTextForNumber(number: Int) -> String {
return "(number)"
}
Example #1
Pure functions
• There is a return value
• No side effects
• Result depends only on input values
• There is a return value ✅
• Result depends only on input values ✅
func labelTextForNumber(number: Int) -> String {
return "(number)"
}
Example #1
Pure functions
• There is a return value
• No side effects
• Result depends only on input values
• There is a return value ✅
• No side effects ✅
• Result depends only on input values ✅
func labelTextForNumber(number: Int) -> String {
return "(number)"
}
Example #1
Pure functions
• There is a return value
• No side effects
• Result depends only on input values
• There is a return value ✅
• No side effects ✅
• Result depends only on input values ✅
func labelTextForNumber(number: Int) -> String {
return "(number)"
}
Example #1
Pure
function
Pure functions
• There is a return value
• No side effects
• Result depends only on input values
• There is a return value ✅
• No side effects ✅
• Result depends only on input values ✅
func labelTextForNumber(number: Int) -> String {
return "(number)"
}
Example #1
self.numberLabel.text = self.labelTextForNumber(1)
Pure
function
Pure functions
func teenagers() -> [Person] {
return self.people.filter { $0.age > 12 && $0.age < 20 }
}
• There is a return value
• No side effects
• Result depends only on input values
Example #2
Pure functions
func teenagers() -> [Person] {
return self.people.filter { $0.age > 12 && $0.age < 20 }
}
• There is a return value
• No side effects
• Result depends only on input values
• There is a return value ✅
Example #2
Pure functions
func teenagers() -> [Person] {
return self.people.filter { $0.age > 12 && $0.age < 20 }
}
• There is a return value
• No side effects
• Result depends only on input values
• There is a return value ✅
• No side effects ✅
Example #2
Pure functions
func teenagers() -> [Person] {
return self.people.filter { $0.age > 12 && $0.age < 20 }
}
• There is a return value
• No side effects
• Result depends only on input values
• There is a return value ✅
• No side effects ✅
Example #2
• Result depends only on input values ❌
Pure functions
func teenagers() -> [Person] {
return self.people.filter { $0.age > 12 && $0.age < 20 }
}
• There is a return value
• No side effects
• Result depends only on input values
• There is a return value ✅
• No side effects ✅
Example #2
• Result depends only on input values ❌
How would you test it?
Pure functions
func teenagersFromPeople(people: [Person]) -> [Person] {
return people.filter { $0.age > 12 && $0.age < 20 }
}
• There is a return value
• No side effects
• Result depends only on input values
Example #2
Pure functions
func teenagersFromPeople(people: [Person]) -> [Person] {
return people.filter { $0.age > 12 && $0.age < 20 }
}
• There is a return value
• No side effects
• Result depends only on input values
• There is a return value ✅
Example #2
Pure functions
func teenagersFromPeople(people: [Person]) -> [Person] {
return people.filter { $0.age > 12 && $0.age < 20 }
}
• There is a return value
• No side effects
• Result depends only on input values
• There is a return value ✅
Example #2
• Result depends only on input values ✅
Pure functions
func teenagersFromPeople(people: [Person]) -> [Person] {
return people.filter { $0.age > 12 && $0.age < 20 }
}
• There is a return value
• No side effects
• Result depends only on input values
• There is a return value ✅
• No side effects ✅
Example #2
• Result depends only on input values ✅
Pure functions
func teenagersFromPeople(people: [Person]) -> [Person] {
return people.filter { $0.age > 12 && $0.age < 20 }
}
• There is a return value
• No side effects
• Result depends only on input values
• There is a return value ✅
• No side effects ✅
Example #2
• Result depends only on input values ✅
Pure
function
Pure functions
func teenagersFromPeople(people: [Person]) -> [Person] {
return people.filter { $0.age > 12 && $0.age < 20 }
}
Example #2
func test15YearsOldIsTeenager() {
let filter = PeopleFilter() // System Under Test
let someone = Person(name: "asd", age: 15)
let input = [someone]
let output = filter.teenagersFromPeople(input)
XCTAssertEqual(output.count, 1)
if output.count == 1 {
XCTAssertEqual(output.first!, someone)
}
}
Pure
function
100%
unit-testable!
Pure functions
• There is a return value
• No side effects
• Result depends only on input values
func randomCharacterFromString(string: String) -> String {
let maxNumber = UInt32((string as NSString).length)
let randomNumber = Int(arc4random_uniform(maxNumber))
let range = NSRange(location: randomNumber, length: 1)
return (string as NSString).substringWithRange(range)
}
Example #3
Pure functions
• There is a return value
• No side effects
• Result depends only on input values
• There is a return value ✅
func randomCharacterFromString(string: String) -> String {
let maxNumber = UInt32((string as NSString).length)
let randomNumber = Int(arc4random_uniform(maxNumber))
let range = NSRange(location: randomNumber, length: 1)
return (string as NSString).substringWithRange(range)
}
Example #3
Pure functions
• There is a return value
• No side effects
• Result depends only on input values
• There is a return value ✅
• No side effects ✅
func randomCharacterFromString(string: String) -> String {
let maxNumber = UInt32((string as NSString).length)
let randomNumber = Int(arc4random_uniform(maxNumber))
let range = NSRange(location: randomNumber, length: 1)
return (string as NSString).substringWithRange(range)
}
Example #3
Pure functions
• There is a return value
• No side effects
• Result depends only on input values
• There is a return value ✅
• No side effects ✅
• Result depends only on input values ❌
func randomCharacterFromString(string: String) -> String {
let maxNumber = UInt32((string as NSString).length)
let randomNumber = Int(arc4random_uniform(maxNumber))
let range = NSRange(location: randomNumber, length: 1)
return (string as NSString).substringWithRange(range)
}
Example #3
Pure functions
• There is a return value
• No side effects
• Result depends only on input values
• There is a return value ✅
• No side effects ✅
• Result depends only on input values ❌
func randomCharacterFromString(string: String) -> String {
let maxNumber = UInt32((string as NSString).length)
let randomNumber = Int(arc4random_uniform(maxNumber))
let range = NSRange(location: randomNumber, length: 1)
return (string as NSString).substringWithRange(range)
}
Example #3
Functions involving randomness can never be pure functions
Pure functions
• There is a return value
• No side effects
• Result depends only on input values
• There is a return value ✅
• No side effects ✅
• Result depends only on input values ❌
func randomCharacterFromString(string: String) -> String {
let maxNumber = UInt32((string as NSString).length)
let randomNumber = Int(arc4random_uniform(maxNumber))
let range = NSRange(location: randomNumber, length: 1)
return (string as NSString).substringWithRange(range)
}
Example #3
Functions involving randomness can never be pure functions
They are not unit-testable, because we can't know what expected result is
Pure functions
• There is a return value
• No side effects
• Result depends only on input values
• There is a return value ✅
• No side effects ✅
• Result depends only on input values ❌
func randomCharacterFromString(string: String) -> String {
let maxNumber = UInt32((string as NSString).length)
let randomNumber = Int(arc4random_uniform(maxNumber))
let range = NSRange(location: randomNumber, length: 1)
return (string as NSString).substringWithRange(range)
}
Example #3
Functions involving randomness can never be pure functions
They are not unit-testable, because we can't know what expected result is , unless…
Pure functions
• There is a return value
• No side effects
• Result depends only on input values
func randomCharacterFromString(string: String, seed: Int) -> String {
let maxNumber = Int32((string as NSString).length)
srand(UInt32(seed)) // Configure the randomizer's seed
let randomNumber = Int(rand() % maxNumber)
let range = NSRange(location: randomNumber, length: 1)
return (string as NSString).substringWithRange(range)
}
Example #3
, unless…
Pure functions
• There is a return value
• No side effects
• Result depends only on input values
• There is a return value ✅
func randomCharacterFromString(string: String, seed: Int) -> String {
let maxNumber = Int32((string as NSString).length)
srand(UInt32(seed)) // Configure the randomizer's seed
let randomNumber = Int(rand() % maxNumber)
let range = NSRange(location: randomNumber, length: 1)
return (string as NSString).substringWithRange(range)
}
Example #3
, unless…
Pure functions
• There is a return value
• No side effects
• Result depends only on input values
• There is a return value ✅
• Result depends only on input values ✅
func randomCharacterFromString(string: String, seed: Int) -> String {
let maxNumber = Int32((string as NSString).length)
srand(UInt32(seed)) // Configure the randomizer's seed
let randomNumber = Int(rand() % maxNumber)
let range = NSRange(location: randomNumber, length: 1)
return (string as NSString).substringWithRange(range)
}
Example #3
, unless…
Pure functions
• There is a return value
• No side effects
• Result depends only on input values
• There is a return value ✅
• No side effects ✅
• Result depends only on input values ✅
func randomCharacterFromString(string: String, seed: Int) -> String {
let maxNumber = Int32((string as NSString).length)
srand(UInt32(seed)) // Configure the randomizer's seed
let randomNumber = Int(rand() % maxNumber)
let range = NSRange(location: randomNumber, length: 1)
return (string as NSString).substringWithRange(range)
}
Example #3
, unless…
Pure functions
• There is a return value
• No side effects
• Result depends only on input values
• There is a return value ✅
• No side effects ✅
• Result depends only on input values ✅
func randomCharacterFromString(string: String, seed: Int) -> String {
let maxNumber = Int32((string as NSString).length)
srand(UInt32(seed)) // Configure the randomizer's seed
let randomNumber = Int(rand() % maxNumber)
let range = NSRange(location: randomNumber, length: 1)
return (string as NSString).substringWithRange(range)
}
Example #3
, unless…
Pure
function
Pure functions
Pure functions
Higher order functions
Protocol-oriented
programming
Immutability
Generic
programming
Pattern matching
MVVM
If you start applying these little yet valuable concepts…
Your brain starts to think in different ways and your mind
gets open to learn more and more!
If you start applying these little yet valuable concepts…
Your brain starts to think in different ways and your mind
gets open to learn more and more!
But also…
The intention of your code is clearer
If you start applying these little yet valuable concepts…
Your brain starts to think in different ways and your mind
gets open to learn more and more!
But also…
The intention of your code is clearer
If you start applying these little yet valuable concepts…
Your brain starts to think in different ways and your mind
gets open to learn more and more!
But also…
Code is easier to understand for others
The intention of your code is clearer
If you start applying these little yet valuable concepts…
Your brain starts to think in different ways and your mind
gets open to learn more and more!
But also…
Code is easier to understand for others
Less headaches when maintaining each others’ code
The intention of your code is clearer
If you start applying these little yet valuable concepts…
Your brain starts to think in different ways and your mind
gets open to learn more and more!
But also…
Code is easier to understand for others
Less headaches when maintaining each others’ code
More effectiveness, more productivity
What Swift can teach us all
What Swift can teach us all
What Swift can teach us all
What Swift can teach us all
What Swift can teach us all

More Related Content

Viewers also liked

Panic! at the Disco
Panic! at the Disco Panic! at the Disco
Panic! at the Disco Alarmclock24
 
NYCC 2014 (Bionicle)
NYCC 2014 (Bionicle)NYCC 2014 (Bionicle)
NYCC 2014 (Bionicle)rusbionicle
 
Working report on insurance company
Working report on insurance companyWorking report on insurance company
Working report on insurance companyAndey786
 
Mavropoulos theofanis
Mavropoulos theofanisMavropoulos theofanis
Mavropoulos theofanisTheofanis2014
 
Brainstormers astro quiz prelims answer
Brainstormers astro quiz  prelims answerBrainstormers astro quiz  prelims answer
Brainstormers astro quiz prelims answerFarzan Kuttan
 
Ohjeistus onnistuneen sisältöstrategian luomiseen ja verkkokauppa-analytiikkaan
Ohjeistus onnistuneen sisältöstrategian luomiseen ja  verkkokauppa-analytiikkaanOhjeistus onnistuneen sisältöstrategian luomiseen ja  verkkokauppa-analytiikkaan
Ohjeistus onnistuneen sisältöstrategian luomiseen ja verkkokauppa-analytiikkaanannaemilia
 
SEO pro eshopy a jejich majitele/správce - Eshopvíkend 2015 :-)
SEO pro eshopy a jejich majitele/správce - Eshopvíkend 2015 :-)SEO pro eshopy a jejich majitele/správce - Eshopvíkend 2015 :-)
SEO pro eshopy a jejich majitele/správce - Eshopvíkend 2015 :-)Jakub Kašparů
 
โครงการผู้บำเพ็ญประโยชน์
โครงการผู้บำเพ็ญประโยชน์โครงการผู้บำเพ็ญประโยชน์
โครงการผู้บำเพ็ญประโยชน์panomkon
 
Optimalizace cílení, skóre kvality a novinky v Adwords API v201601
Optimalizace cílení, skóre kvality a novinky v Adwords API v201601Optimalizace cílení, skóre kvality a novinky v Adwords API v201601
Optimalizace cílení, skóre kvality a novinky v Adwords API v201601Jakub Kašparů
 

Viewers also liked (16)

Panic! at the Disco
Panic! at the Disco Panic! at the Disco
Panic! at the Disco
 
Pre o-net math6
Pre o-net math6Pre o-net math6
Pre o-net math6
 
NYCC 2014 (Bionicle)
NYCC 2014 (Bionicle)NYCC 2014 (Bionicle)
NYCC 2014 (Bionicle)
 
Working report on insurance company
Working report on insurance companyWorking report on insurance company
Working report on insurance company
 
Mavropoulos theofanis
Mavropoulos theofanisMavropoulos theofanis
Mavropoulos theofanis
 
Brainstormers astro quiz prelims answer
Brainstormers astro quiz  prelims answerBrainstormers astro quiz  prelims answer
Brainstormers astro quiz prelims answer
 
Ohjeistus onnistuneen sisältöstrategian luomiseen ja verkkokauppa-analytiikkaan
Ohjeistus onnistuneen sisältöstrategian luomiseen ja  verkkokauppa-analytiikkaanOhjeistus onnistuneen sisältöstrategian luomiseen ja  verkkokauppa-analytiikkaan
Ohjeistus onnistuneen sisältöstrategian luomiseen ja verkkokauppa-analytiikkaan
 
Pie
PiePie
Pie
 
SEO pro eshopy a jejich majitele/správce - Eshopvíkend 2015 :-)
SEO pro eshopy a jejich majitele/správce - Eshopvíkend 2015 :-)SEO pro eshopy a jejich majitele/správce - Eshopvíkend 2015 :-)
SEO pro eshopy a jejich majitele/správce - Eshopvíkend 2015 :-)
 
Caring
CaringCaring
Caring
 
Tik 3
Tik 3Tik 3
Tik 3
 
E4
E4E4
E4
 
โครงการผู้บำเพ็ญประโยชน์
โครงการผู้บำเพ็ญประโยชน์โครงการผู้บำเพ็ญประโยชน์
โครงการผู้บำเพ็ญประโยชน์
 
Desigualdade social
Desigualdade socialDesigualdade social
Desigualdade social
 
Optimalizace cílení, skóre kvality a novinky v Adwords API v201601
Optimalizace cílení, skóre kvality a novinky v Adwords API v201601Optimalizace cílení, skóre kvality a novinky v Adwords API v201601
Optimalizace cílení, skóre kvality a novinky v Adwords API v201601
 
Presentation1
Presentation1Presentation1
Presentation1
 

Similar to What Swift can teach us all

7 Habits For a More Functional Swift
7 Habits For a More Functional Swift7 Habits For a More Functional Swift
7 Habits For a More Functional SwiftJason Larsen
 
Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02Seri Moth
 
Programming Language Swift Overview
Programming Language Swift OverviewProgramming Language Swift Overview
Programming Language Swift OverviewKaz Yoshikawa
 
Swiftの関数型っぽい部分
Swiftの関数型っぽい部分Swiftの関数型っぽい部分
Swiftの関数型っぽい部分bob_is_strange
 
A swift introduction to Swift
A swift introduction to SwiftA swift introduction to Swift
A swift introduction to SwiftGiordano Scalzo
 
Empathic Programming - How to write comprehensible code
Empathic Programming - How to write comprehensible codeEmpathic Programming - How to write comprehensible code
Empathic Programming - How to write comprehensible codeMario Gleichmann
 
Introduction to Kotlin.pptx
Introduction to Kotlin.pptxIntroduction to Kotlin.pptx
Introduction to Kotlin.pptxAzharFauzan9
 
01 Introduction to Kotlin - Programming in Kotlin.pptx
01 Introduction to Kotlin - Programming in Kotlin.pptx01 Introduction to Kotlin - Programming in Kotlin.pptx
01 Introduction to Kotlin - Programming in Kotlin.pptxIvanZawPhyo
 
Monoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and CatsMonoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and CatsPhilip Schwarz
 
Generics and Inference
Generics and InferenceGenerics and Inference
Generics and InferenceRichard Fox
 
Paradigmas de Linguagens de Programacao - Aula #4
Paradigmas de Linguagens de Programacao - Aula #4Paradigmas de Linguagens de Programacao - Aula #4
Paradigmas de Linguagens de Programacao - Aula #4Ismar Silveira
 
Intro to Advanced JavaScript
Intro to Advanced JavaScriptIntro to Advanced JavaScript
Intro to Advanced JavaScriptryanstout
 
Introduction to Swift programming language.
Introduction to Swift programming language.Introduction to Swift programming language.
Introduction to Swift programming language.Icalia Labs
 
Tuga IT 2017 - What's new in C# 7
Tuga IT 2017 - What's new in C# 7Tuga IT 2017 - What's new in C# 7
Tuga IT 2017 - What's new in C# 7Paulo Morgado
 
No excuses, switch to kotlin
No excuses, switch to kotlinNo excuses, switch to kotlin
No excuses, switch to kotlinThijs Suijten
 

Similar to What Swift can teach us all (20)

7 Habits For a More Functional Swift
7 Habits For a More Functional Swift7 Habits For a More Functional Swift
7 Habits For a More Functional Swift
 
Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02
 
Programming Language Swift Overview
Programming Language Swift OverviewProgramming Language Swift Overview
Programming Language Swift Overview
 
Swiftの関数型っぽい部分
Swiftの関数型っぽい部分Swiftの関数型っぽい部分
Swiftの関数型っぽい部分
 
Pooya Khaloo Presentation on IWMC 2015
Pooya Khaloo Presentation on IWMC 2015Pooya Khaloo Presentation on IWMC 2015
Pooya Khaloo Presentation on IWMC 2015
 
A swift introduction to Swift
A swift introduction to SwiftA swift introduction to Swift
A swift introduction to Swift
 
Empathic Programming - How to write comprehensible code
Empathic Programming - How to write comprehensible codeEmpathic Programming - How to write comprehensible code
Empathic Programming - How to write comprehensible code
 
Introduction to Kotlin.pptx
Introduction to Kotlin.pptxIntroduction to Kotlin.pptx
Introduction to Kotlin.pptx
 
01 Introduction to Kotlin - Programming in Kotlin.pptx
01 Introduction to Kotlin - Programming in Kotlin.pptx01 Introduction to Kotlin - Programming in Kotlin.pptx
01 Introduction to Kotlin - Programming in Kotlin.pptx
 
Monoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and CatsMonoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and Cats
 
Generics and Inference
Generics and InferenceGenerics and Inference
Generics and Inference
 
Scala in Practice
Scala in PracticeScala in Practice
Scala in Practice
 
Paradigmas de Linguagens de Programacao - Aula #4
Paradigmas de Linguagens de Programacao - Aula #4Paradigmas de Linguagens de Programacao - Aula #4
Paradigmas de Linguagens de Programacao - Aula #4
 
Intro to Advanced JavaScript
Intro to Advanced JavaScriptIntro to Advanced JavaScript
Intro to Advanced JavaScript
 
Introduction to Swift programming language.
Introduction to Swift programming language.Introduction to Swift programming language.
Introduction to Swift programming language.
 
Scala introduction
Scala introductionScala introduction
Scala introduction
 
Scala - brief intro
Scala - brief introScala - brief intro
Scala - brief intro
 
Tuga IT 2017 - What's new in C# 7
Tuga IT 2017 - What's new in C# 7Tuga IT 2017 - What's new in C# 7
Tuga IT 2017 - What's new in C# 7
 
No excuses, switch to kotlin
No excuses, switch to kotlinNo excuses, switch to kotlin
No excuses, switch to kotlin
 
Kotlin
KotlinKotlin
Kotlin
 

Recently uploaded

Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension AidPhilip Schwarz
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...harshavardhanraghave
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsJhone kinadey
 
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...OnePlan Solutions
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionSolGuruz
 
How to Choose the Right Laravel Development Partner in New York City_compress...
How to Choose the Right Laravel Development Partner in New York City_compress...How to Choose the Right Laravel Development Partner in New York City_compress...
How to Choose the Right Laravel Development Partner in New York City_compress...software pro Development
 
Define the academic and professional writing..pdf
Define the academic and professional writing..pdfDefine the academic and professional writing..pdf
Define the academic and professional writing..pdfPearlKirahMaeRagusta1
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...Health
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVshikhaohhpro
 
10 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 202410 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 2024Mind IT Systems
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsAlberto González Trastoy
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfkalichargn70th171
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comFatema Valibhai
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplatePresentation.STUDIO
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsArshad QA
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdfWave PLM
 
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...kalichargn70th171
 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech studentsHimanshiGarg82
 

Recently uploaded (20)

Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial Goals
 
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with Precision
 
How to Choose the Right Laravel Development Partner in New York City_compress...
How to Choose the Right Laravel Development Partner in New York City_compress...How to Choose the Right Laravel Development Partner in New York City_compress...
How to Choose the Right Laravel Development Partner in New York City_compress...
 
Define the academic and professional writing..pdf
Define the academic and professional writing..pdfDefine the academic and professional writing..pdf
Define the academic and professional writing..pdf
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 
10 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 202410 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 2024
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.com
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf
 
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS LiveVip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
 
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
 

What Swift can teach us all

  • 1. What Swift can teach us all! or… How Swift has opened our minds
  • 2. What Swift can teach us all! or… How Swift has opened our minds
  • 3. Let’s talk about functions!
  • 4. Let’s talk about functions! *pun intended fun
  • 5. Let’s talk about functions! Did you know that in Swift you can assign functions to variables? No, seriously… *pun intended fun
  • 6. var number = 4 // A boring Int Let’s talk about functions! Did you know that in Swift you can assign functions to variables? No, seriously… *pun intended fun
  • 7. var number = 4 // A boring Int Let’s talk about functions! var sum = { (a: Float, b: Float) in return a + b } Did you know that in Swift you can assign functions to variables? No, seriously… *pun intended fun
  • 8. var number = 4 // A boring Int Let’s talk about functions! var sum = { (a: Float, b: Float) in return a + b } Did you know that in Swift you can assign functions to variables? No, seriously… *pun intended fun // A fun...ction
  • 9. var number = 4 // A boring Int Let’s talk about functions! var sum = { (a: Float, b: Float) in return a + b } Did you know that in Swift you can assign functions to variables? No, seriously… *pun intended fun // A fun...ction
  • 10. var number = 4 // A boring Int Let’s talk about functions! var sum = { (a: Float, b: Float) in return a + b } let four = sum(2, 2) print(four) // Prints 4.0 Did you know that in Swift you can assign functions to variables? No, seriously… *pun intended fun // A fun...ction
  • 11. Why the hell would I need that…?
  • 15. Higher order functions Moment… What’s that? Roughly speaking… "A higher order function is a function that accepts functions as parameters" - Some guy.
  • 16. let sum = { (a: Float, b: Float) in return a + b } let subtract = { (a: Float, b: Float) in return a - b } let multiply = { (a: Float, b: Float) in return a * b } let divide = { (a: Float, b: Float) in return a / b } func main() { let eight = operateOn(6, and: 2, usingFunction: sum) let four = operateOn(6, and: 2, usingFunction: subtract) let twelve = operateOn(6, and: 2, usingFunction: multiply) let three = operateOn(6, and: 2, usingFunction: divide) } func operateOn(a: Float, and b: Float, usingFunction f: (Float, Float) -> Float) -> Float { return f(a, b) }
  • 17. let sum = { (a: Float, b: Float) in return a + b } let subtract = { (a: Float, b: Float) in return a - b } let multiply = { (a: Float, b: Float) in return a * b } let divide = { (a: Float, b: Float) in return a / b } func main() { let eight = operateOn(6, and: 2, usingFunction: sum) let four = operateOn(6, and: 2, usingFunction: subtract) let twelve = operateOn(6, and: 2, usingFunction: multiply) let three = operateOn(6, and: 2, usingFunction: divide) } func operateOn(a: Float, and b: Float, usingFunction f: (Float, Float) -> Float) -> Float { return f(a, b) } We have defined 4 functions as variables.
  • 18. let sum = { (a: Float, b: Float) in return a + b } let subtract = { (a: Float, b: Float) in return a - b } let multiply = { (a: Float, b: Float) in return a * b } let divide = { (a: Float, b: Float) in return a / b } func main() { let eight = operateOn(6, and: 2, usingFunction: sum) let four = operateOn(6, and: 2, usingFunction: subtract) let twelve = operateOn(6, and: 2, usingFunction: multiply) let three = operateOn(6, and: 2, usingFunction: divide) } func operateOn(a: Float, and b: Float, usingFunction f: (Float, Float) -> Float) -> Float { return f(a, b) } We have defined 4 functions as variables. We pass in those functions in the operateOn call "as if" they were variables… (well, they actually are)
  • 19. operateOn is a higher order function, because it accepts a function as an input parameter. let sum = { (a: Float, b: Float) in return a + b } let subtract = { (a: Float, b: Float) in return a - b } let multiply = { (a: Float, b: Float) in return a * b } let divide = { (a: Float, b: Float) in return a / b } func main() { let eight = operateOn(6, and: 2, usingFunction: sum) let four = operateOn(6, and: 2, usingFunction: subtract) let twelve = operateOn(6, and: 2, usingFunction: multiply) let three = operateOn(6, and: 2, usingFunction: divide) } func operateOn(a: Float, and b: Float, usingFunction f: (Float, Float) -> Float) -> Float { return f(a, b) } We have defined 4 functions as variables. We pass in those functions in the operateOn call "as if" they were variables… (well, they actually are)
  • 20. Still… Why the hell would I need that???
  • 21. Let’s see a more practical example…
  • 22. func teenagersFromPeople(people: [Person]) -> [Person] { var teenagers = [Person]() for person in people { if person.age > 12 && person.age < 20 { teenagers.append(person) } } return teenagers } Let’s see a more practical example…
  • 23. func teenagersFromPeople(people: [Person]) -> [Person] { var teenagers = [Person]() for person in people { if person.age > 12 && person.age < 20 { teenagers.append(person) } } return teenagers } Mutability Let’s see a more practical example…
  • 24. func teenagersFromPeople(people: [Person]) -> [Person] { var teenagers = [Person]() for person in people { if person.age > 12 && person.age < 20 { teenagers.append(person) } } return teenagers } Mutability Danger! Let’s see a more practical example…
  • 25. func teenagersFromPeople(people: [Person]) -> [Person] { var teenagers = [Person]() for person in people { if person.age > 12 && person.age < 20 { teenagers.append(person) } } return teenagers } Mutability Danger! But… Hold on… Why? Let’s see a more practical example…
  • 26. Nope, it’s not this… func teenagersFromPeople(people: [Person]) -> [Person] { var teenagers = [Person]() for person in people { if person.age > 12 && person.age < 20 { teenagers.append(person) } } return teenagers } Mutability Danger! But… Hold on… Why? Let’s see a more practical example…
  • 27. Mutability: By using mutable variables, we are not 100% sure what the value of the variable at some point is. It could be modified somewhere, and that leads to the fact that we need to keep track of where that variable is being used and how it’s being modified. In smaller cases like this, it’s easy to keep track, but…
  • 28. for jsonRow in rows { var post = Post(json: jsonRow) let postId = jsonRow["id"].stringValue if let storedPost = realm.objects(Post).filter("id = %@", postId).first { post = storedPost post!.refresh(jsonRow, endpoint: self.basePath as! ServerEndpoint) post!.postType = PostType(rawValue:(storedPost.postType.rawValue | feedType.rawValue)) updates.append(post!.id) } else { post = Post(json: jsonRow, endpoint: self.basePath as! ServerEndpoint) post!.postType = feedType additions.append(postId) } realm.add(post!, update: true) } How about this…?
  • 29. for jsonRow in rows { var post = Post(json: jsonRow) let postId = jsonRow["id"].stringValue if let storedPost = realm.objects(Post).filter("id = %@", postId).first { post = storedPost post!.refresh(jsonRow, endpoint: self.basePath as! ServerEndpoint) post!.postType = PostType(rawValue:(storedPost.postType.rawValue | feedType.rawValue)) updates.append(post!.id) } else { post = Post(json: jsonRow, endpoint: self.basePath as! ServerEndpoint) post!.postType = feedType additions.append(postId) } realm.add(post!, update: true) } How about this…? Let’s keep track of post…
  • 30. for jsonRow in rows { var post = Post(json: jsonRow) let postId = jsonRow["id"].stringValue if let storedPost = realm.objects(Post).filter("id = %@", postId).first { post = storedPost post!.refresh(jsonRow, endpoint: self.basePath as! ServerEndpoint) post!.postType = PostType(rawValue:(storedPost.postType.rawValue | feedType.rawValue)) updates.append(post!.id) } else { post = Post(json: jsonRow, endpoint: self.basePath as! ServerEndpoint) post!.postType = feedType additions.append(postId) } realm.add(post!, update: true) } How about this…? Let’s keep track of post…
  • 31. for jsonRow in rows { var post = Post(json: jsonRow) let postId = jsonRow["id"].stringValue if let storedPost = realm.objects(Post).filter("id = %@", postId).first { post = storedPost post!.refresh(jsonRow, endpoint: self.basePath as! ServerEndpoint) post!.postType = PostType(rawValue:(storedPost.postType.rawValue | feedType.rawValue)) updates.append(post!.id) } else { post = Post(json: jsonRow, endpoint: self.basePath as! ServerEndpoint) post!.postType = feedType additions.append(postId) } realm.add(post!, update: true) } How about this…? At this point, we can’t easily ensure what the post is going to be… Let’s keep track of post…
  • 32. func teenagersFromPeople(people: [Person]) -> [Person] { var teenagers = [Person]() for person in people { if person.age > 12 && person.age < 20 { teenagers.append(person) } } return teenagers } Back to our example… Could we replace it, somehow, such that we avoid mutability?
  • 33. func teenagersFromPeople(people: [Person]) -> [Person] { let teenagers: [Person] teenagers = people.filter({ (person) -> Bool in return person.age > 12 && person.age < 20 }) return teenagers } Higher order functions to the rescue!
  • 34. func teenagersFromPeople(people: [Person]) -> [Person] { let teenagers: [Person] teenagers = people.filter({ (person) -> Bool in return person.age > 12 && person.age < 20 }) return teenagers } Higher order functions to the rescue! // let :)
  • 35. func teenagersFromPeople(people: [Person]) -> [Person] { let teenagers: [Person] teenagers = people.filter({ (person) -> Bool in return person.age > 12 && person.age < 20 }) return teenagers } Higher order functions to the rescue! // let 😊
  • 36. func teenagersFromPeople(people: [Person]) -> [Person] { let teenagers: [Person] teenagers = people.filter({ (person) -> Bool in return person.age > 12 && person.age < 20 }) return teenagers } Higher order functions to the rescue! // let 😊 Yes, emojis are allowed in Swift source code… ✌
  • 37. func teenagersFromPeople(people: [Person]) -> [Person] { let teenagers: [Person] teenagers = people.filter({ (person) -> Bool in return person.age > 12 && person.age < 20 }) return teenagers } Higher order functions to the rescue! // let 😊 Yes, we are tending to become hippies Yes, emojis are allowed in Swift source code… ✌
  • 38. func teenagersFromPeople(people: [Person]) -> [Person] { let teenagers: [Person] teenagers = people.filter({ (person) -> Bool in return person.age > 12 && person.age < 20 }) return teenagers } Higher order functions to the rescue! // let 😊 Yes, we are tending to become hippies Yes, emojis are allowed in Swift source code… ✌
  • 39. func teenagersFromPeople(people: [Person]) -> [Person] { let teenagers: [Person] teenagers = people.filter({ (person) -> Bool in return person.age > 12 && person.age < 20 }) return teenagers } Higher order functions to the rescue! // let 😊 Yes, we are tending to become hippies Yes, emojis are allowed in Swift source code… ✌ If we could just simplify this…
  • 40. func teenagersFromPeople(people: [Person]) -> [Person] { let teenagers: [Person] teenagers = people.filter { $0.age > 12 && $0.age < 20 } return teenagers } Simplicity, oh, yeah…
  • 41. func teenagersFromPeople(people: [Person]) -> [Person] { return people.filter { $0.age > 12 && $0.age < 20 } } Even simpler, baby…
  • 42. func teenagersFromPeople(people: [Person]) -> [Person] { var teenagers = [Person]() for person in people { if person.age > 12 && person.age < 20 { teenagers.append(person) } } return teenagers } Not preferred Higher order functions
  • 43. func teenagersFromPeople(people: [Person]) -> [Person] { var teenagers = [Person]() for person in people { if person.age > 12 && person.age < 20 { teenagers.append(person) } } return teenagers } Not preferred func teenagersFromPeople(people: [Person]) -> [Person] { return people.filter { $0.age > 12 && $0.age < 20 } } Preferred Higher order functions
  • 44. func teenagersFromPeople(people: [Person]) -> [Person] { var teenagers = [Person]() for person in people { if person.age > 12 && person.age < 20 { teenagers.append(person) } } return teenagers } Not preferred func teenagersFromPeople(people: [Person]) -> [Person] { return people.filter { $0.age > 12 && $0.age < 20 } } Preferred FILTER Higher order functions
  • 45. func idsFromPeople(people: [Person]) -> [String] { var ids = [String]() for person in people { ids.append(person.id) } return ids } Not preferred Higher order functions
  • 46. func idsFromPeople(people: [Person]) -> [String] { var ids = [String]() for person in people { ids.append(person.id) } return ids } func idsFromPeople(people: [Person]) -> [String] { return people.map { $0.id } } Preferred Not preferred Higher order functions
  • 47. func idsFromPeople(people: [Person]) -> [String] { var ids = [String]() for person in people { ids.append(person.id) } return ids } func idsFromPeople(people: [Person]) -> [String] { return people.map { $0.id } } Preferred Not preferred MAP Higher order functions
  • 48. func childrenCountFromPeople(people: [Person]) -> Int { var count = 0 for person in people { count += person.children.count } return count } Not preferred Higher order functions
  • 49. func childrenCountFromPeople(people: [Person]) -> Int { var count = 0 for person in people { count += person.children.count } return count } func childrenCountFromPeople(people: [Person]) -> Int { return people.reduce(0) { $0 + $1.children.count } } Preferred Not preferred Higher order functions
  • 50. func childrenCountFromPeople(people: [Person]) -> Int { var count = 0 for person in people { count += person.children.count } return count } func childrenCountFromPeople(people: [Person]) -> Int { return people.reduce(0) { $0 + $1.children.count } } Preferred Not preferred REDUCE Higher order functions
  • 51. FILTER MAP REDUCE You want some of the original elements You want new elements based on the original elements You want a result based on the original elements
  • 53. Pure functions A pure function is a function where the return value is only determined by its input values, without observable side effects.
  • 54. Pure functions A pure function is a function where the return value is only determined by its input values, without observable side effects. • There is a return value
  • 55. Pure functions A pure function is a function where the return value is only determined by its input values, without observable side effects. • There is a return value • Result depends only on input values
  • 56. Pure functions A pure function is a function where the return value is only determined by its input values, without observable side effects. • There is a return value • No side effects • Result depends only on input values
  • 57. Pure functions A pure function is a function where the return value is only determined by its input values, without observable side effects. • There is a return value • No side effects • Result depends only on input values 100% unit-testable!
  • 58. • There is a return value • No side effects • Result depends only on input values func configureLabelTextWithNumber(number: Int) { self.numberLabel.text = "(number)" } Example #1 Pure functions
  • 59. • There is a return value • No side effects • Result depends only on input values func configureLabelTextWithNumber(number: Int) { self.numberLabel.text = "(number)" } • There is a return value ❌ Example #1 Pure functions
  • 60. • There is a return value • No side effects • Result depends only on input values func configureLabelTextWithNumber(number: Int) { self.numberLabel.text = "(number)" } • There is a return value ❌ • Result depends only on input values ✅ Example #1 Pure functions
  • 61. • There is a return value • No side effects • Result depends only on input values func configureLabelTextWithNumber(number: Int) { self.numberLabel.text = "(number)" } • There is a return value ❌ • No side effects ❌ • Result depends only on input values ✅ Example #1 Pure functions
  • 62. • There is a return value • No side effects • Result depends only on input values func configureLabelTextWithNumber(number: Int) { self.numberLabel.text = "(number)" } • There is a return value ❌ • No side effects ❌ • Result depends only on input values ✅ Example #1 Functions using "self.something" are a call to side effects Pure functions
  • 63. • There is a return value • No side effects • Result depends only on input values func labelTextForNumber(number: Int) -> String { return "(number)" } Example #1 Pure functions
  • 64. • There is a return value • No side effects • Result depends only on input values • There is a return value ✅ func labelTextForNumber(number: Int) -> String { return "(number)" } Example #1 Pure functions
  • 65. • There is a return value • No side effects • Result depends only on input values • There is a return value ✅ • Result depends only on input values ✅ func labelTextForNumber(number: Int) -> String { return "(number)" } Example #1 Pure functions
  • 66. • There is a return value • No side effects • Result depends only on input values • There is a return value ✅ • No side effects ✅ • Result depends only on input values ✅ func labelTextForNumber(number: Int) -> String { return "(number)" } Example #1 Pure functions
  • 67. • There is a return value • No side effects • Result depends only on input values • There is a return value ✅ • No side effects ✅ • Result depends only on input values ✅ func labelTextForNumber(number: Int) -> String { return "(number)" } Example #1 Pure function Pure functions
  • 68. • There is a return value • No side effects • Result depends only on input values • There is a return value ✅ • No side effects ✅ • Result depends only on input values ✅ func labelTextForNumber(number: Int) -> String { return "(number)" } Example #1 self.numberLabel.text = self.labelTextForNumber(1) Pure function Pure functions
  • 69. func teenagers() -> [Person] { return self.people.filter { $0.age > 12 && $0.age < 20 } } • There is a return value • No side effects • Result depends only on input values Example #2 Pure functions
  • 70. func teenagers() -> [Person] { return self.people.filter { $0.age > 12 && $0.age < 20 } } • There is a return value • No side effects • Result depends only on input values • There is a return value ✅ Example #2 Pure functions
  • 71. func teenagers() -> [Person] { return self.people.filter { $0.age > 12 && $0.age < 20 } } • There is a return value • No side effects • Result depends only on input values • There is a return value ✅ • No side effects ✅ Example #2 Pure functions
  • 72. func teenagers() -> [Person] { return self.people.filter { $0.age > 12 && $0.age < 20 } } • There is a return value • No side effects • Result depends only on input values • There is a return value ✅ • No side effects ✅ Example #2 • Result depends only on input values ❌ Pure functions
  • 73. func teenagers() -> [Person] { return self.people.filter { $0.age > 12 && $0.age < 20 } } • There is a return value • No side effects • Result depends only on input values • There is a return value ✅ • No side effects ✅ Example #2 • Result depends only on input values ❌ How would you test it? Pure functions
  • 74. func teenagersFromPeople(people: [Person]) -> [Person] { return people.filter { $0.age > 12 && $0.age < 20 } } • There is a return value • No side effects • Result depends only on input values Example #2 Pure functions
  • 75. func teenagersFromPeople(people: [Person]) -> [Person] { return people.filter { $0.age > 12 && $0.age < 20 } } • There is a return value • No side effects • Result depends only on input values • There is a return value ✅ Example #2 Pure functions
  • 76. func teenagersFromPeople(people: [Person]) -> [Person] { return people.filter { $0.age > 12 && $0.age < 20 } } • There is a return value • No side effects • Result depends only on input values • There is a return value ✅ Example #2 • Result depends only on input values ✅ Pure functions
  • 77. func teenagersFromPeople(people: [Person]) -> [Person] { return people.filter { $0.age > 12 && $0.age < 20 } } • There is a return value • No side effects • Result depends only on input values • There is a return value ✅ • No side effects ✅ Example #2 • Result depends only on input values ✅ Pure functions
  • 78. func teenagersFromPeople(people: [Person]) -> [Person] { return people.filter { $0.age > 12 && $0.age < 20 } } • There is a return value • No side effects • Result depends only on input values • There is a return value ✅ • No side effects ✅ Example #2 • Result depends only on input values ✅ Pure function Pure functions
  • 79. func teenagersFromPeople(people: [Person]) -> [Person] { return people.filter { $0.age > 12 && $0.age < 20 } } Example #2 func test15YearsOldIsTeenager() { let filter = PeopleFilter() // System Under Test let someone = Person(name: "asd", age: 15) let input = [someone] let output = filter.teenagersFromPeople(input) XCTAssertEqual(output.count, 1) if output.count == 1 { XCTAssertEqual(output.first!, someone) } } Pure function 100% unit-testable! Pure functions
  • 80. • There is a return value • No side effects • Result depends only on input values func randomCharacterFromString(string: String) -> String { let maxNumber = UInt32((string as NSString).length) let randomNumber = Int(arc4random_uniform(maxNumber)) let range = NSRange(location: randomNumber, length: 1) return (string as NSString).substringWithRange(range) } Example #3 Pure functions
  • 81. • There is a return value • No side effects • Result depends only on input values • There is a return value ✅ func randomCharacterFromString(string: String) -> String { let maxNumber = UInt32((string as NSString).length) let randomNumber = Int(arc4random_uniform(maxNumber)) let range = NSRange(location: randomNumber, length: 1) return (string as NSString).substringWithRange(range) } Example #3 Pure functions
  • 82. • There is a return value • No side effects • Result depends only on input values • There is a return value ✅ • No side effects ✅ func randomCharacterFromString(string: String) -> String { let maxNumber = UInt32((string as NSString).length) let randomNumber = Int(arc4random_uniform(maxNumber)) let range = NSRange(location: randomNumber, length: 1) return (string as NSString).substringWithRange(range) } Example #3 Pure functions
  • 83. • There is a return value • No side effects • Result depends only on input values • There is a return value ✅ • No side effects ✅ • Result depends only on input values ❌ func randomCharacterFromString(string: String) -> String { let maxNumber = UInt32((string as NSString).length) let randomNumber = Int(arc4random_uniform(maxNumber)) let range = NSRange(location: randomNumber, length: 1) return (string as NSString).substringWithRange(range) } Example #3 Pure functions
  • 84. • There is a return value • No side effects • Result depends only on input values • There is a return value ✅ • No side effects ✅ • Result depends only on input values ❌ func randomCharacterFromString(string: String) -> String { let maxNumber = UInt32((string as NSString).length) let randomNumber = Int(arc4random_uniform(maxNumber)) let range = NSRange(location: randomNumber, length: 1) return (string as NSString).substringWithRange(range) } Example #3 Functions involving randomness can never be pure functions Pure functions
  • 85. • There is a return value • No side effects • Result depends only on input values • There is a return value ✅ • No side effects ✅ • Result depends only on input values ❌ func randomCharacterFromString(string: String) -> String { let maxNumber = UInt32((string as NSString).length) let randomNumber = Int(arc4random_uniform(maxNumber)) let range = NSRange(location: randomNumber, length: 1) return (string as NSString).substringWithRange(range) } Example #3 Functions involving randomness can never be pure functions They are not unit-testable, because we can't know what expected result is Pure functions
  • 86. • There is a return value • No side effects • Result depends only on input values • There is a return value ✅ • No side effects ✅ • Result depends only on input values ❌ func randomCharacterFromString(string: String) -> String { let maxNumber = UInt32((string as NSString).length) let randomNumber = Int(arc4random_uniform(maxNumber)) let range = NSRange(location: randomNumber, length: 1) return (string as NSString).substringWithRange(range) } Example #3 Functions involving randomness can never be pure functions They are not unit-testable, because we can't know what expected result is , unless… Pure functions
  • 87. • There is a return value • No side effects • Result depends only on input values func randomCharacterFromString(string: String, seed: Int) -> String { let maxNumber = Int32((string as NSString).length) srand(UInt32(seed)) // Configure the randomizer's seed let randomNumber = Int(rand() % maxNumber) let range = NSRange(location: randomNumber, length: 1) return (string as NSString).substringWithRange(range) } Example #3 , unless… Pure functions
  • 88. • There is a return value • No side effects • Result depends only on input values • There is a return value ✅ func randomCharacterFromString(string: String, seed: Int) -> String { let maxNumber = Int32((string as NSString).length) srand(UInt32(seed)) // Configure the randomizer's seed let randomNumber = Int(rand() % maxNumber) let range = NSRange(location: randomNumber, length: 1) return (string as NSString).substringWithRange(range) } Example #3 , unless… Pure functions
  • 89. • There is a return value • No side effects • Result depends only on input values • There is a return value ✅ • Result depends only on input values ✅ func randomCharacterFromString(string: String, seed: Int) -> String { let maxNumber = Int32((string as NSString).length) srand(UInt32(seed)) // Configure the randomizer's seed let randomNumber = Int(rand() % maxNumber) let range = NSRange(location: randomNumber, length: 1) return (string as NSString).substringWithRange(range) } Example #3 , unless… Pure functions
  • 90. • There is a return value • No side effects • Result depends only on input values • There is a return value ✅ • No side effects ✅ • Result depends only on input values ✅ func randomCharacterFromString(string: String, seed: Int) -> String { let maxNumber = Int32((string as NSString).length) srand(UInt32(seed)) // Configure the randomizer's seed let randomNumber = Int(rand() % maxNumber) let range = NSRange(location: randomNumber, length: 1) return (string as NSString).substringWithRange(range) } Example #3 , unless… Pure functions
  • 91. • There is a return value • No side effects • Result depends only on input values • There is a return value ✅ • No side effects ✅ • Result depends only on input values ✅ func randomCharacterFromString(string: String, seed: Int) -> String { let maxNumber = Int32((string as NSString).length) srand(UInt32(seed)) // Configure the randomizer's seed let randomNumber = Int(rand() % maxNumber) let range = NSRange(location: randomNumber, length: 1) return (string as NSString).substringWithRange(range) } Example #3 , unless… Pure function Pure functions
  • 92. Pure functions Higher order functions Protocol-oriented programming Immutability Generic programming Pattern matching MVVM
  • 93. If you start applying these little yet valuable concepts… Your brain starts to think in different ways and your mind gets open to learn more and more!
  • 94. If you start applying these little yet valuable concepts… Your brain starts to think in different ways and your mind gets open to learn more and more! But also…
  • 95. The intention of your code is clearer If you start applying these little yet valuable concepts… Your brain starts to think in different ways and your mind gets open to learn more and more! But also…
  • 96. The intention of your code is clearer If you start applying these little yet valuable concepts… Your brain starts to think in different ways and your mind gets open to learn more and more! But also… Code is easier to understand for others
  • 97. The intention of your code is clearer If you start applying these little yet valuable concepts… Your brain starts to think in different ways and your mind gets open to learn more and more! But also… Code is easier to understand for others Less headaches when maintaining each others’ code
  • 98. The intention of your code is clearer If you start applying these little yet valuable concepts… Your brain starts to think in different ways and your mind gets open to learn more and more! But also… Code is easier to understand for others Less headaches when maintaining each others’ code More effectiveness, more productivity