Contents

tryCompactMap(_:)

Calls an error-throwing closure with each received element and publishes any returned optional that has a value.

Declaration

func tryCompactMap<T>(_ transform: @escaping (Self.Output) throws -> T?) -> Publishers.TryCompactMap<Self, T>

Parameters

  • transform:

    An error-throwing closure that receives a value and returns an optional value.

Return Value

Any non-nil optional results of calling the supplied closure.

Discussion

Use tryCompactMap(_:) to remove nil elements from a publisher’s stream based on an error-throwing closure you provide. If the closure throws an error, the publisher cancels the upstream publisher and sends the thrown error to the downstream subscriber as a Failure.

The following example uses an array of numbers as the source for a collection-based publisher. A tryCompactMap(_:) operator consumes each integer from the publisher and uses a dictionary to transform the numbers from its Arabic to Roman numerals, as an optional String.

If the closure called by tryCompactMap(_:) fails to look up a Roman numeral, it returns the optional String (unknown).

If the closure called by tryCompactMap(_:) determines the input is 0, it throws an error. The tryCompactMap(_:) operator catches this error and stops publishing, sending a Subscribers.Completion.failure(_:) that wraps the error.

struct ParseError: Error {}
func romanNumeral(from: Int) throws -> String? {
    let romanNumeralDict: [Int : String] =
        [1: "I", 2: "II", 3: "III", 4: "IV", 5: "V"]
    guard from != 0 else { throw ParseError() }
    return romanNumeralDict[from]
}
let numbers = [6, 5, 4, 3, 2, 1, 0]
cancellable = numbers.publisher
    .tryCompactMap { try romanNumeral(from: $0) }
    .sink(
          receiveCompletion: { print ("\($0)") },
          receiveValue: { print ("\($0)", terminator: " ") }
     )

// Prints: "(Unknown) V IV III II I failure(ParseError())"

See Also

Filtering elements