Guides/FirstNonNil.md
Returns the first non-nil result obtained from applying the given
transformation to the elements of the sequence.
let strings = ["three", "3.14", "-5", "2"]
if let firstInt = strings.firstNonNil({ Int($0) }) {
print(firstInt)
// -5
}
Like first(where:), this method stops iterating the sequence once a match is
found. Use firstNonNil(_:) to avoid having to apply a transformation twice:
let strings = ["three", "3.14", "-5", "2"]
if let firstIntAsString = strings.first(where: { Int($0) != nil }) {
let firstInt = Int(firstIntAsString)! // :(
// ...
}
This method's behavior can also be approximated using compactMap(_:):
let strings = ["three", "3.14", "-5", "2"]
if let firstInt = strings.compactMap({ Int($0) }).first {
// ...
}
However, unlike firstNonNil(_:) and first(where:), compactMap(_:) does not
stop iterating the sequence once the first match is found. Adding .lazy fixes
this, at the cost of requiring an escaping closure that you cannot throw from:
let strings = ["three", "3.14", "-5", "2"]
if let firstInt = strings.lazy.compactMap({ Int($0) }).first {
// ...
}
The firstNonNil(_:) method is added as an extension method on the Sequence
protocol:
public extension Sequence {
func firstNonNil<Result>(
_ transform: (Element) throws -> Result?
) rethrows -> Result?
}
firstNonNil(_:) is an O(n) operation, where n is the number of
elements at the start of the sequence that result in nil when applying the
transformation.
Some alternative names were considered:
compactMapFirst(_:)first(mapping:)firstSome(_:)firstMap(_:)Haskell: Haskell includes the firstJust method, which has the same
semantics as the firstNonNil(_:) method.
Rust: Rust includes the find_map method, which has the same semantics as
the firstNonNil(_:) method.
Scala: Scala includes the collectFirst method, which has the same
semantics as the firstNonNil(_:) method.