CombineCommunity / CombineExt

CombineExt provides a collection of operators, publishers and utilities for Combine, that are not provided by Apple themselves, but are common in other Reactive Frameworks and standards.
https://combine.community
MIT License
1.72k stars 151 forks source link

combineLatest doesn't emit any value if the input array is empty #118

Closed DesmanLead closed 2 years ago

DesmanLead commented 2 years ago

Example:

func foo(publishers: [AnyPublisher<String, Never>]) {
    publishers
        .combineLatest()
        .sink { strings in print(strings) }
        .store(in: &cancellables)
}

Nothing will be printed if publishers is an empty array. Feels like the correct behavior is to emit an empty array of String in this case. The caller doesn't need a special handling of an empty input case then.

freak4pc commented 2 years ago

Hey, I believe this was discussed already here - This behavior is matched with that of RxSwift and Reactive Streams spec. An empty publisher doesn't mean an empty value - on the contrary, it means the lack of values.

DesmanLead commented 2 years ago

Do you have any use cases in mind when this behavior makes sense? Maybe, I'm biased by our use cases.

freak4pc commented 2 years ago

It's not about a use case it's about guarantees and rules of the operator :) combineLatest combines publishers once they emit at least a single value - if one of the publishers never emits anything, the entirety of the combination shouldn't. The fact it's an array and not just two or three individual publishers is just an implementation detail, the rules themselves don't change :)

DesmanLead commented 2 years ago

Sounds reasonable, I'm convinced :) Do you have any elegant solution in mind for the case when either all the publishers emit at least one value or there are no publishers? I can't say I'm completely satisfied with if input.isEmpty { return Just([]).eraseToAnyPublisher() } %) Thanks for sharing your thoughts!

jasdev commented 2 years ago

@DesmanLead: .replaceEmpty(with: []) should do the trick. ✅

Even though Ext didn’t decide to go this route, there’s sound theoretical reason for why an empty array should be emitted. I wrote a bit about it here, if you’re curious.