Two (or more) optionals in Swift
ios, option-type, swift
Solution
(Updated for Swift >=3)
"Double optionals" can be useful, and the Swift blog entry "Optionals Case Study: valuesForKeys" describes an application.
Here is a simplified example:
let dict : [String : String?] = ["a" : "foo" , "b" : nil]
is a dictionary with optional strings as values. Therefore
let val = dict[key]
has the type `String??` aka `Optional<Optional<String>>`. It is `.none` (or `nil`) if the key is not present in the dictionary, and `.some(x)` otherwise. In the second case, `x` is a `String?` aka `Optional<String>` and can be `.none` (or `nil`) or `.some(s)` where `s` is a String.
You can use nested optional binding to check for the various cases:
for key in ["a", "b", "c"] {
let val = dict[key]
if let x = val {
if let s = x {
print("\(key): \(s)")
} else {
print("\(key): nil")
}
} else {
print("\(key): not present")
}
}
Output:
a: foo
b: nil
c: not present
It might be instructive to see how the same can be achieved with pattern matching in a switch-statement:
let val = dict[key]
switch val {
case .some(.some(let s)):
print("\(key): \(s)")
case .some(.none):
print("\(key): nil")
case .none:
print("\(key): not present")
}
or, using the `x?` pattern as a synonym for `.some(x)`:
let val = dict[key]
switch val {
case let (s??):
print("\(key): \(s)")
case let (s?):
print("\(key): nil")
case nil:
print("\(key): not present")
}
(I do not know a sensible application for more deeply nested optionals.)
Problem
While watching an Apple's video about LLDB debugger I found something I can't find an explanation for; he was talking about optional values when he wrote: ``` var optional: String? = nil; //This is ok, a common optional var twice_optional: String?? = nil; //What is this and why's this useful?? ``` I opened a playground and started trying it out and realized that you can write as many as `?` as you want, and then unwrap them with the same number of `!`. I understand the concept of wrapping/unwrapping a variable but can't think of a situation where I would like to wrap a value 4, 5 or 6 times.