I initially found the lack of this feature to be a problem when working on a function called tryFutureMap
in my QuickCombine library. This function basically allows you to perform an asynchronous, one to one, mapping operation that may produce an error. Here is the definition of one of the overloads of the function:
public extension Publisher where Failure == Never {
func tryFutureMap<T, U>(_ transform: @escaping (_ value: Output, _ promise: @escaping (Result<T, U>) -> Void) -> Void) -> Publishers.TryFutureMap<Publishers.SetFailureType<Self, U>, T> where U: Error {
return Publishers.TryFutureMap(upstream: self.setFailureType(to: U.self), transform: transform)
}
}
It is standard in a call to tryFutureMap
to make at least two calls to the promise
argument of the transform
closure, one for a successful result and one for a failure, although there are many scenarios where one might want to call promise
more than two times. The problem here is that, for its intended use case, it is not practical to provide tryFutureMap
with a single-expression closure, and as such, Swift requires me to explicitly state the type for promise
, which is always a fairly long type signature that is easy to mess up.
Just("Hello")
.tryFutureMap { (value, promise: @escaping (Result<Int, CustomError>) -> Void) in
if value == "Hello" {
promise(.success(1))
} else {
promise(.failure(CustomError()))
}
}
With the ability to specialize the type of a generic function at its call site, the above usage of tryFutureMap
could be replaced with the following:
Just("Hello")
.tryFutureMap<Int, CustomError> { value, promise in
if value == "Hello" {
promise(.success(1))
} else {
promise(.failure(CustomError()))
}
}
In this case, the user should not have to tell Swift the type of the promise
argument as Swift knows it already with exception for the specialized types for T
and U
. Having to state the additional information seems error prone and congests the call-site. Generic function specialization would remove this redundancy.