‘In Swift, nil is a
polymorphic superhero’
Chris Lattner (probably)
Slide 4
Slide 4 text
Name that nil in one
What is the Type of nil?
Slide 5
Slide 5 text
Name that nil in one
(A wild guess — is it an Optional?)
enum Optional {
case None
case Some(T)
}
Slide 6
Slide 6 text
Name that nil in one (a gentle start)
let x:Bool? = nil
???
Slide 7
Slide 7 text
Name that nil in one (a gentle start)
let x:Bool? = nil
let x = Optional.None
Slide 8
Slide 8 text
Name that nil in one
"9".toInt() != nil
???
Slide 9
Slide 9 text
Name that nil in one
"9".toInt() != nil
“9".toInt() != Optional.None
Slide 10
Slide 10 text
map(nil) { $0 + "!" }
Name that nil in one (Type inference required)
???
Slide 11
Slide 11 text
Name that nil in one (Type inference required)
map(nil) { $0 + "!" }
map(Optional.None) { $0 + "!" }
Slide 12
Slide 12 text
Name that nil in one (that’s easy)
nil < 0
???
Slide 13
Slide 13 text
Name that nil in one (hmmm?)
nil < 0
??? Int (Yes?)
Slide 14
Slide 14 text
Name that nil in one (Eh!?)
nil < 0
Optional.None < Optional.Some(0)
Slide 15
Slide 15 text
protocol NilLiteralConvertible {
init(nilLiteral: ())
}
enum Optional : NilLiteralConvertible {
init(nilLiteral: ()) {
self = None
}
}
How to get an Optional from ‘nil’
Slide 16
Slide 16 text
nil is a phantom
The advantage of Optionals is not what
they add to the language, but what they
enable to be removed: nil
Slide 17
Slide 17 text
Escape from the land of the nils
In many languages nil roams free and
you must take precautions to remain safe
Slide 18
Slide 18 text
Mandatory, ridiculous code example
let dict = [1:[2:[3:[4:[5:"Hello"]]]]]
Slide 19
Slide 19 text
let dict = [1:[2:[3:[4:[5:"Hello"]]]]]
let v = dict[1][2][3][4][5]
A language with nil
You've gotta ask yourself one question: “Do I feel lucky?”
Slide 20
Slide 20 text
Well, do ya, punk? … (Yep)
let dict = [1:[2:[3:[4:[5:"Hello"]]]]]
let v = dict[1][2][3][4][5]
Possible results:
1. v == "Hello"
Slide 21
Slide 21 text
let dict = [1:[2:[3:[4:[5:"Hello"]]]]]
let v = dict[1][2][3][4][0]
Possible results:
1. v == "Hello"
2. v == nil
Well, do ya, punk? … (Not sure?)
Slide 22
Slide 22 text
let dict = [1:[2:[3:[4:[5:"Hello"]]]]]
let v = dict[1][0][3][4][5]
Possible results:
1. v == "Hello"
2. v == nil
3. Boom!!!
Well, do ya, punk? … (Argh!)
Slide 23
Slide 23 text
Swift Dictionary subscripting
struct Dictionary {
subscript (key: Key) -> Value?
}
return value is Optional
Slide 24
Slide 24 text
Optionals are simple
enum Optional {
case None
case Some(T)
}
Slide 25
Slide 25 text
Swift style (Houston, we've got a problem)
let dict = [1:[2:[3:[4:[5:"Hello"]]]]]
let a:String?
!
switch dict[1] {
case .None : a = .None
case .Some(let d) :
switch d[2] {
case .None : a = .None
case .Some(let d) :
switch d[3] {
case .None : a = .None
case .Some(let d) :
switch d[4] {
case .None : a = .None
case .Some(let d) :
switch d[5] {
case .None : a = .None
case .Some(let x) : a = x
}
}
}
}
}
Slide 26
Slide 26 text
Swift style (safe, yet insane)
let a:String?
!
switch dict[1] {
case .None : a = .None
case .Some(let d) :
switch d[2] {
case .None : a = .None
case .Some(let d) :
switch d[3] {
case .None : a = .None
case .Some(let d) :
switch d[4] {
case .None : a = .None
case .Some(let d) :
switch d[5] {
case .None : a = .None
case .Some(let x) : a = x
}
}
}
}
}
Slide 27
Slide 27 text
What did Optional chaining ever do for us?
let v = dict[1]?[2]?[3]?[4]?[5]
Slide 28
Slide 28 text
let v = dict[1]?[2]?[3]?[4]?[5]
Monadic bind
What did Optional chaining ever do for us?
Slide 29
Slide 29 text
You probably won’t break a leg
Optionals are the ‘green piste’
on the monadic mountain
Slide 30
Slide 30 text
>>=
No! Not the custom infix operator!
Slide 31
Slide 31 text
infix operator >>= {associativity left}
Declaration of a custom infix operator
The monadic nature of Optional chaining
let v = dict[1]?[2]?[3]?[4]?[5]
let v = dict[1] >>= { $0[2] }
>>= { $0[3] }
>>= { $0[4] }
>>= { $0[5] }
Slide 37
Slide 37 text
Two monadic binds are better than one
‘if let’ syntax
Slide 38
Slide 38 text
let v = dict[1]?[2]?[3]?[4]?[5]
let v:String?
!
if let a = dict[1], b = a[2], c = b[3], d = c[4], e = d[5] {
v = e
} else {
v = .None
}
Two monadic binds are better than one
Slide 39
Slide 39 text
Three monadic binds are better than one
flatMap
Slide 40
Slide 40 text
flatMap – a method on Optionals
enum Optional {
func flatMap(f: T -> U?) -> U?
}
Slide 41
Slide 41 text
let v = dict[1]?[2]?[3]?[4]?[5]
let v = dict[1].flatMap { $0[2] }
.flatMap { $0[3] }
.flatMap { $0[4] }
.flatMap { $0[5] }
Three monadic binds are better than one
Slide 42
Slide 42 text
Conclusion
Slide 43
Slide 43 text
Conclusion
• The nil is dead. Long live the Optional.
Slide 44
Slide 44 text
Conclusion
• The nil is dead. Long live the Optional.
• Code without nil is saner code.
Slide 45
Slide 45 text
Conclusion
• The nil is dead. Long live the Optional.
• Code without nil is saner code.
• Optionals are simple values, but do add complexity.
Slide 46
Slide 46 text
Conclusion
• The nil is dead. Long live the Optional.
• Code without nil is saner code.
• Optionals are simple values, but do add complexity.
• Monadic bind is a natural way to tame the complexity.
Slide 47
Slide 47 text
Conclusion
• The nil is dead. Long live the Optional.
• Code without nil is saner code.
• Optionals are simple values, but do add complexity.
• Monadic bind is a natural way to tame the complexity.
• Swift deals with Optionals monadically, so do you.