belozierov / SwiftCoroutine

Swift coroutines for iOS, macOS and Linux.
https://belozierov.github.io/SwiftCoroutine
MIT License
836 stars 51 forks source link

Typed Errors in CoFuture #9

Closed AverageHelper closed 4 years ago

AverageHelper commented 4 years ago

Is there a reason that CoFuture is not generic to its Error result type as well as its Value? As it is, similarly to Swift's untyped throwing functions, I'm always needing a default clause when I switch over CoFuture failure cases. I assume there's a good reason for designing it this way....

belozierov commented 4 years ago

@AverageHelper Thanks for your suggestion. I’ve considered this option, but apart from generic Error it can also throw CoFutureError.canceled (in future other CoFutureError might be added). It’s necessary for completing coroutines when it is suspended by await() and canceling CoFuture. Alternatively, you can try this:

extension CoPromise {

    func success<T, E>(_ value: T) where Value == Result<T, E> {
        success(.success(value))
    }

    func fail<T, E: Error>(_ error: E) where Value == Result<T, E> {
        success(.failure(error))
    }

}

func makeFuture() -> CoFuture<Result<Int, SomeError>> {
    let promise = CoPromise<Result<Int, SomeError>>()
    promise.success(1)
    return promise
}

func useFuture() {
    DispatchQueue.global().startCoroutine {
        let future = self.makeFuture()

        switch try future.await() {
        case .success(let int):
        case .failure(let someError):
        }
    }
}

Or you can create some CoFutureWrapper<Value, Failure: Error>, which will be a wrapper for CoFuture<Result<Int, SomeError>>.

Currently, I’m not planning to add this feature because I want to keep the library api as simple as possible.

belozierov commented 4 years ago

@AverageHelper It's even better to create typealiases:

typealias CoFutureResult<T, E: Error> = CoFuture<Result<T, E>>
typealias CoPromiseResult<T, E: Error> = CoPromise<Result<T, E>>

func makeFuture() -> CoFutureResult<Int, SomeError>