Given functions multiply()
and convert()
(minimal examples of the concept, I'm actually planning to query a remote server inside each function), what is a shorter way to implement multiplyAndConvert()
?
// call two async functions passing the result the from the first
// as the argument to the second
multiplyAndConvert(3).startWithResult { val in
print("\(val.value!)")
}
func convert(_ val: Int) -> SignalProducer<String, NSError> {
return SignalProducer<String, NSError> { observer, _ in
observer.send(value: String(val))
observer.sendCompleted()
}
}
func multiply(_ val: Int) -> SignalProducer<Int, NSError> {
return SignalProducer<Int,NSError> { observer, _ in
observer.send(value: val * 2)
observer.sendCompleted()
}
}
func multiplyAndConvert(_ val: Int) -> SignalProducer<String, NSError> {
return SignalProducer<String, NSError> { observer, _ in
multiply(val).startWithResult { res2 in
switch res2 {
case .success(let val2):
convert(val2).startWithResult { res3 in
switch res3 {
case .success(let val3):
observer.send(value:val3)
observer.sendCompleted()
case .failure(let err):
observer.send(error:err)
}
}
case .failure(let err):
observer.send(error: err)
}
observer.sendCompleted()
}
}
}
I know there has to be a more elegant way to do this, but I'm stumped as to what it is. I've played around with map, flatMap, flatten, and most other functions but can't find a better solution.
func multiplyAndConvert(_ val: Int) -> SignalProducer<String, NSError> {
return multiply(val).flatMap(.concat) { multipliedVal in
return convert(multipliedVal)
}
}
you can also pass convert
directly as the second arg to flatMap rather than giving it a closure, since it is already the right type (Int -> SignalProducer<String, NSError>
)
multiply(val).flatMap(.concat, transform: convert)
but if the convert
function references self
in your expanded code this can result in retain cycles, in which case you would need a pass a closure capturing [weak self]
what the flatMap
does here is takes your multiply signal:
-----.value(multipliedValue)-.completed
and maps it into a signal-of-signals using the supplied closure:
.value(convertedMultipliedValue)
/
----x-.completed
and then "flattens" this signal-of-signals (using .Concat flattening strategy, which flattens the signal-of-signals by concatenating all the child signals- but that doesn't matter here because we are only flattening a single child signal) to give us:
----.value(convertedMultipliedValue)-.completed