Adding print to Just changes behaviour of Combine sequence

Code block below produces different results depending on if print is commented or not:

Code Block
import Combine
var cancellables = Set<AnyCancellable>()
enum FruitError: Error {
case bad
}
var fruit = "apple"
func getFruit() -> String {
fruit
}
Just(getFruit)
//.print()
.map{$0()}
.flatMap { value -> AnyPublisher<String, FruitError> in
print("in flat map \(value)")
if value == "apple" {
fruit = "pineapple"
return Fail(error: FruitError.bad).eraseToAnyPublisher()
}
return Just("banana").setFailureType(to: FruitError.self).eraseToAnyPublisher()
}
.retry(1)
.sink(receiveCompletion: { print($0) }, receiveValue: {print($0)})
.store(in: &cancellables)

Without print:
Code Block
in flat map apple
in flat map apple
failure


With print:
Code Block
in flat map apple
in flat map pineapple
banana
receive finished
finished
receive finished
Why does print or any other debug operator(breakpoint or handleEvent) change behaviour of sequence?






using .share() instead of a .print() does the same trick for me.


How about Deferred?

Deferred{Just(getFruit())} allows retry with just value and without need of extra map.

Code Block
Deferred{Just(getFruit())}
    .flatMap { value -> AnyPublisher<String, FruitError> in
        print("in flat map \(value)")
        if value == "apple" {
            fruit = "pineapple"
            return Fail(error: FruitError.bad).eraseToAnyPublisher()
        }
        return Just("banana").setFailureType(to: FruitError.self).eraseToAnyPublisher()
    }
    .retry(1)
    .sink(receiveCompletion: { print($0) }, receiveValue: {print($0)})
    .store(in: &cancellables)


Yes, Deferred allows to call Just on retry but doesn't explain why print changes behaviour of sequence. Anyway, @squirrel987 thank you for suggestion!




Sorry I don't have an answer, I think it's a great question. I played with your example code and I'm just as puzzled. I hope someone else can answer.
Adding print to Just changes behaviour of Combine sequence
 
 
Q