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.
(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.)
var tripleOptional: String???
is same as
var tripleOptional: Optional<Optional<Optional<String>>>
I cannot think of any useful use of it, but its there because optionals are generic work for any type of object. Nested optionals are like box put into another box or array but into an other array.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With