问题
Swift documentation of flatMap reads:
Returns an array containing the non-nil results of calling the given transformation with each element of this sequence.
In the following examples when return type of ElementOfResult
is left to the compiler to infer flatMap
works as documented, yet on line 5 when ElementOfResult
is specified, thus inferred to an Optional<String>
type it seems that flatMap
stops filtering out nil
's.
Why is it doing that?
~ swift
Welcome to Apple Swift version 3.0.2 (swiftlang-800.0.63 clang-800.0.42.1). Type :help for assistance.
1> let words = ["1989", nil, "Fearless", nil, "Red"]
words: [String?] = 5 values {
[0] = "1989"
[1] = nil
[2] = "Fearless"
[3] = nil
[4] = "Red"
}
2> words.flatMap { $0 }
$R0: [String] = 3 values {
[0] = "1989"
[1] = "Fearless"
[2] = "Red"
}
3> let resultTypeInferred = words.flatMap { $0 }
resultTypeInferred: [String] = 3 values {
[0] = "1989"
[1] = "Fearless"
[2] = "Red"
}
4> let resultTypeSpecified: [String?] = words.flatMap { $0 }
resultTypeSpecified: [String?] = 5 values {
[0] = "1989"
[1] = nil
[2] = "Fearless"
[3] = nil
[4] = "Red"
}
回答1:
Here's the definition of flatMap()
public func flatMap<ElementOfResult>(_ transform: (Element) throws -> ElementOfResult?) rethrows -> [ElementOfResult]
When you set the type of resultTypeSpecified
to [String?]
, you tell the compiler that ElementOfResult
is Optional<String>
.
Your transform closure has a type of (String?) -> Optional<Optional<String>>
.
flatMap
will take away 1 "layer" of optionals but not 2 layers.
Hopefully this example will makes things clearer:
let input: [String??] = [
Optional.some(Optional.some("1989")),
Optional.some(Optional.none),
Optional.some(Optional.some("Fearless")),
Optional.some(Optional.none),
Optional.some(Optional.some("Red"))
]
let output = input.flatMap({ $0 })
来源:https://stackoverflow.com/questions/42214880/flatmap-does-not-filter-out-nil-when-elementofresult-is-inferred-to-be-optional