SlideShare a Scribd company logo
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 theofanis
Theofanis2014
 
Brainstormers astro quiz prelims answer
Brainstormers astro quiz  prelims answerBrainstormers astro quiz  prelims answer
Brainstormers astro quiz prelims answer
Farzan 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-analytiikkaan
annaemilia
 
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 v201601
Jakub 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 Swift
Jason 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 Overview
Kaz Yoshikawa
 
Swiftの関数型っぽい部分
Swiftの関数型っぽい部分Swiftの関数型っぽい部分
Swiftの関数型っぽい部分
bob_is_strange
 
Pooya Khaloo Presentation on IWMC 2015
Pooya Khaloo Presentation on IWMC 2015Pooya Khaloo Presentation on IWMC 2015
Pooya Khaloo Presentation on IWMC 2015
Iran Entrepreneurship Association
 
A swift introduction to Swift
A swift introduction to SwiftA swift introduction to Swift
A swift introduction to Swift
Giordano 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 code
Mario Gleichmann
 
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
IvanZawPhyo
 
Introduction to Kotlin.pptx
Introduction to Kotlin.pptxIntroduction to Kotlin.pptx
Introduction to Kotlin.pptx
AzharFauzan9
 
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
Philip Schwarz
 
Generics and Inference
Generics and InferenceGenerics and Inference
Generics and Inference
Richard Fox
 
Scala in Practice
Scala in PracticeScala in Practice
Scala in Practice
Francesco Usai
 
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
Ismar Silveira
 
Intro to Advanced JavaScript
Intro to Advanced JavaScriptIntro to Advanced JavaScript
Intro to Advanced JavaScript
ryanstout
 
Introduction to Swift programming language.
Introduction to Swift programming language.Introduction to Swift programming language.
Introduction to Swift programming language.
Icalia Labs
 
Scala - brief intro
Scala - brief introScala - brief intro
Scala - brief intro
Razvan Cojocaru
 
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
Paulo Morgado
 
No excuses, switch to kotlin
No excuses, switch to kotlinNo excuses, switch to kotlin
No excuses, switch to kotlin
Thijs Suijten
 
Kotlin
KotlinKotlin

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
 
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
 
Introduction to Kotlin.pptx
Introduction to Kotlin.pptxIntroduction to Kotlin.pptx
Introduction to 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

TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERRORTROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
Tier1 app
 
Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024
Globus
 
Accelerate Enterprise Software Engineering with Platformless
Accelerate Enterprise Software Engineering with PlatformlessAccelerate Enterprise Software Engineering with Platformless
Accelerate Enterprise Software Engineering with Platformless
WSO2
 
Software Testing Exam imp Ques Notes.pdf
Software Testing Exam imp Ques Notes.pdfSoftware Testing Exam imp Ques Notes.pdf
Software Testing Exam imp Ques Notes.pdf
MayankTawar1
 
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Globus
 
First Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User EndpointsFirst Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User Endpoints
Globus
 
Explore Modern SharePoint Templates for 2024
Explore Modern SharePoint Templates for 2024Explore Modern SharePoint Templates for 2024
Explore Modern SharePoint Templates for 2024
Sharepoint Designs
 
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
Juraj Vysvader
 
SOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar Research Team: Latest Activities of IntelBrokerSOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar
 
How to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good PracticesHow to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good Practices
Globus
 
How Does XfilesPro Ensure Security While Sharing Documents in Salesforce?
How Does XfilesPro Ensure Security While Sharing Documents in Salesforce?How Does XfilesPro Ensure Security While Sharing Documents in Salesforce?
How Does XfilesPro Ensure Security While Sharing Documents in Salesforce?
XfilesPro
 
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
informapgpstrackings
 
Strategies for Successful Data Migration Tools.pptx
Strategies for Successful Data Migration Tools.pptxStrategies for Successful Data Migration Tools.pptx
Strategies for Successful Data Migration Tools.pptx
varshanayak241
 
Enhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdfEnhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdf
Globus
 
Why React Native as a Strategic Advantage for Startup Innovation.pdf
Why React Native as a Strategic Advantage for Startup Innovation.pdfWhy React Native as a Strategic Advantage for Startup Innovation.pdf
Why React Native as a Strategic Advantage for Startup Innovation.pdf
ayushiqss
 
Cyaniclab : Software Development Agency Portfolio.pdf
Cyaniclab : Software Development Agency Portfolio.pdfCyaniclab : Software Development Agency Portfolio.pdf
Cyaniclab : Software Development Agency Portfolio.pdf
Cyanic lab
 
Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024
Paco van Beckhoven
 
Advanced Flow Concepts Every Developer Should Know
Advanced Flow Concepts Every Developer Should KnowAdvanced Flow Concepts Every Developer Should Know
Advanced Flow Concepts Every Developer Should Know
Peter Caitens
 
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, BetterWebinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
XfilesPro
 
Providing Globus Services to Users of JASMIN for Environmental Data Analysis
Providing Globus Services to Users of JASMIN for Environmental Data AnalysisProviding Globus Services to Users of JASMIN for Environmental Data Analysis
Providing Globus Services to Users of JASMIN for Environmental Data Analysis
Globus
 

Recently uploaded (20)

TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERRORTROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
 
Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024
 
Accelerate Enterprise Software Engineering with Platformless
Accelerate Enterprise Software Engineering with PlatformlessAccelerate Enterprise Software Engineering with Platformless
Accelerate Enterprise Software Engineering with Platformless
 
Software Testing Exam imp Ques Notes.pdf
Software Testing Exam imp Ques Notes.pdfSoftware Testing Exam imp Ques Notes.pdf
Software Testing Exam imp Ques Notes.pdf
 
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
 
First Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User EndpointsFirst Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User Endpoints
 
Explore Modern SharePoint Templates for 2024
Explore Modern SharePoint Templates for 2024Explore Modern SharePoint Templates for 2024
Explore Modern SharePoint Templates for 2024
 
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
 
SOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar Research Team: Latest Activities of IntelBrokerSOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar Research Team: Latest Activities of IntelBroker
 
How to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good PracticesHow to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good Practices
 
How Does XfilesPro Ensure Security While Sharing Documents in Salesforce?
How Does XfilesPro Ensure Security While Sharing Documents in Salesforce?How Does XfilesPro Ensure Security While Sharing Documents in Salesforce?
How Does XfilesPro Ensure Security While Sharing Documents in Salesforce?
 
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
 
Strategies for Successful Data Migration Tools.pptx
Strategies for Successful Data Migration Tools.pptxStrategies for Successful Data Migration Tools.pptx
Strategies for Successful Data Migration Tools.pptx
 
Enhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdfEnhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdf
 
Why React Native as a Strategic Advantage for Startup Innovation.pdf
Why React Native as a Strategic Advantage for Startup Innovation.pdfWhy React Native as a Strategic Advantage for Startup Innovation.pdf
Why React Native as a Strategic Advantage for Startup Innovation.pdf
 
Cyaniclab : Software Development Agency Portfolio.pdf
Cyaniclab : Software Development Agency Portfolio.pdfCyaniclab : Software Development Agency Portfolio.pdf
Cyaniclab : Software Development Agency Portfolio.pdf
 
Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024
 
Advanced Flow Concepts Every Developer Should Know
Advanced Flow Concepts Every Developer Should KnowAdvanced Flow Concepts Every Developer Should Know
Advanced Flow Concepts Every Developer Should Know
 
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, BetterWebinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
 
Providing Globus Services to Users of JASMIN for Environmental Data Analysis
Providing Globus Services to Users of JASMIN for Environmental Data AnalysisProviding Globus Services to Users of JASMIN for Environmental Data Analysis
Providing Globus Services to Users of JASMIN for Environmental Data Analysis
 

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