Lightening Talk I gave at Inaka in November 2015, after having developed Swift for a while.
It contains some lessons, mostly learned from the functional paradigm, that can be useful for any developer.
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
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)
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…
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
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