262588213843476 · Gist

// `optionalZip` because `zip` caused ambiguity with `Publisher.zip` in the implementation below.
private func optionalZip<Left, Right>(_ pair: (Left?, Right?)) -> (Left, Right)? {
pair.0.flatMap { left in pair.1.map { right in (left, right) } }
}
extension Publisher {
func pairwiseWithDuplicatedStart() -> AnyPublisher<(Output, Output), Failure> {
scan((nil, nil)) { previousPair, next in
optionalZip(previousPair)
.map { ($0.1, next) } ?? (next, next) // (1)
}
.compactMap(optionalZip)
.eraseToAnyPublisher()
}
}
let cancellable = (1...2)
.publisher
.pairwiseWithDuplicatedStart()
.sink(receiveValue: { print($0) })
// Outputs (without the annotations):
// ```
// (1, 1)
// (1, 2)
// ```

Read the original on gist.github.com ↗