Optionals motivation
I call it my billion-dollar mistake. It was the invention of the null reference in 1965. - Tony Hoare
Null (nil) sucks.
It (usually) means the absence of some piece of data
All objects can be null, but many times we KNOW some particular object can't be null, so we don't check
Because of this, when an object is null we may forget to check!
Optionals
swift:
var x: String = "hello" // x can change (var) but can NEVER be nil
// Intro
var xOpt: String? = "hello" // y CAN be nil
// Elimination
if let v = xOpt {
// v can NEVER be nil!
} else {
// xOpt was nil!
}
Optionals
Why the first slide in this section?
swift:
let xOpt: String? = "hello"
if xOpt != nil {
println(xOpt!)
}
AHHH Boolean Blindness
Don't use the postfix "!" on a variable. Ever.
Don't use it. Don't EVER USE IT
optionals
Unfortunately, we have to interop with the unsafely typed Objective-C.
func arrayByAddingObject(_ anObject: AnyObject!) -> [AnyObject]!
(Most) everything in Cocoa is auto-typed to (AnyObject!). This means that the compiler auto-unboxes the optional will let you use the value without checking for nil.
In Swift, this crashes your app. Read the APIs and make sure you check for nil.
optionals
capital "o" optionals
swift:
let xOpt: String? = "hello" // regular optional
let yOpt: Optional<String> = .None
let zOpt: Optional<String> = .Some("hello") // capital "O" Optional
Capital "O" Optionals are actually explicit enums in the language.
They are (mostly) interchangeable! You can do lower-case "O" optional stuff on capital "O" Optionals and vice versa
optional
useful stuff I discovered
If you want an optional stored property of type T that can be "nil" when the initializer finishes:
var storedProp: Optional<String> = .None
BUT extract it with pattern matching when you use it in something that's auto converted to an Objective-C object otherwise the compiler will outputs bad assembly
Optionals
useful stuff that I discovered
swift:
// extending Optional puts methods on optional as well!
extension Optional {
func getOrElse(els: @auto_closure () -> T) -> T {
switch (self) {
case .None:
return els()
case .Some(let t):
return t
}
}
}
Optional
Useful stuff that I discovered
getOrElse (from Scala) is SUPER useful since Pattern matching is a statement and not an expression in swift
let xOpt: Int? = 10
let yOpt: Int? = nil
let z = xOpt.getOrElse(0) + yOpt.getOrElse(1)
var realX: Int = 0
var realY: Int = 1
if let x = xOpt {
realX = x
}
if let y = yOpt {
realY = y
}
let z = x + y
optional
useful stuff that I discovered
Look closely:
func getOrElse(els: @auto_closure () -> T) -> T
It's an @auto_closure
This means that getOrElse short circuits!
You can raise an exception in the els for debugging!
sadness -- dealing with crashes
Extract capital "O" Optionals via pattern before any Objective-C auto conversion occurs
Dictionary<String, Any> will crash at runtime when converted to NSDictionary. Use Dictionary<String, AnyObject>.
(AnyObject is any Objective-C object, Any is protocol<>)
Sadness -- dealing with crashes
Enums with more than one generic type don't work yet
enum Result<T,E> {
case Success(T)
case Error(E)
}
Recursive enums don't work yet
enum Tree<T> {
case Leaf(T)
case Node(Tree<T>, T, Tree<T>)
}
Sadness -- dealing with crashes
Xcode sucks right now
Disable auto-complete
Avoid using the debugger
Sometimes the syntax-highlighter/autocomplete/other engine crashes, but it will keep auto-restarting until it stops crashing