I’ve been experimenting with different options for subscribing on one scheduler and receiving events on another and came across behaviour that I cannot explain. Could somebody help me out?
This code compiles fine:
var subscriptions = Set<AnyCancellable>()
let computationPublisher = Publishers.ExpensiveComputation(duration: 3)
let queue = DispatchQueue(label: "serial queue")
let currentThread = Thread.current.number
print("Start computation publisher on thread \(currentThread)")
computationPublisher
.subscribe(on: queue)
.receive(on: DispatchQueue.main)
.map { $0 } // <- This map doesn't do anything
.map { $0 } // <- This map doesn't do anything either
.sink { value in
let thread = Thread.current.number
print("Received computation: \(value) on thread: \(thread)")
}
.store(in: &subscriptions)
But if I try printing something from the second map I’m getting a type inference error.
computationPublisher
.subscribe(on: queue)
.receive(on: DispatchQueue.main)
.map { $0 } // <- This map doesn't do anything
.map { value in
print("Observed value: \(value)") // <- Adding this print statement throws an error
// Unable to infer type of a closure parameter 'value' in the current context
return value
}
.sink { value in
let thread = Thread.current.number
print("Received computation: \(value) on thread: \(thread)")
}
.store(in: &subscriptions)
Removing the first map
fixes the error, this code compiles:
computationPublisher
.subscribe(on: queue)
.receive(on: DispatchQueue.main)
.map { value in
print("Observed value: \(value)")
return value
}
.sink { value in
let thread = Thread.current.number
print("Received computation: \(value) on thread: \(thread)")
}
.store(in: &subscriptions)
These kind of errors can get rather frustrating 
Thank you for your help!
While it’s not an answer to the question, I found that I can workaround the problem by telling the compiler what I want the return type of anonymous closures to be
computationPublisher
.subscribe(on: queue)
.receive(on: DispatchQueue.main)
.map { $0 }
.map { value -> String in // <- This map will return a string.
print("Observed value: \(value)")
return value
}
.sink { value in
let thread = Thread.current.number
print("Received computation: \(value) on thread: \(thread)")
}
.store(in: &subscriptions)
This compiles again, so that should be enough for me to keep going.
Also, I found this article to be helpful: Tricks and Tips
1 Like