I know that optional chaining like this:
someOptional?.someProperty
is basically
someOptional.map { $0.someProperty }
However, I found that doing both at the same time is not possible:
// someOptional?.someProperty evaluates to an optional type, right?
// so the map method should exist!
someOptional?.someProperty.map(someClosure) // can't find "map"
Here's an MCVE:
let s: String? = "Hello"
s?.hashValue.map(Double.init)
I think writing something like the above is more readable than:
s.map { Double($0.hashValue) }
So I would really like a way to use optional chaining and map
at the same time.
How do I do this?
Apparently, for some reason, wrapping the first part in brackets worked:
(s?.hashValue).map(Double.init)
I think this is somehow due to the ?
having a lower precedence, or that optional chaining doesn't work the same way as other expressions. Adding the brackets might have caused s?.hashValue
to become an expression.
Edit:
Here is the relevant excerpt from the Swift reference:
If a postfix expression that contains an optional-chaining expression is nested inside other postfix expressions, only the outermost expression returns an optional type. In the example below, when c is not nil, its value is unwrapped and used to evaluate .property, the value of which is used to evaluate .performAction(). The entire expression c?.property.performAction() has a value of an optional type.
So s?.hashValue
doesn't actually evaluate to an optional type, because it is nested inside another expression. By adding ()
, I separated it into another expression, manually making it evaluate to an optional type.