Thomvis/BrightFutures

No option to throw an error inside map

Closed this issue · 9 comments

I want to use map and in the map I have a function that can throw an error, in that case, I would like the new future to fail, when i try to do that i get an error "Invalid conversion from throwing function of type '(_) throws -> _' to non-throwing function type '(JSON) -> _'"
is there an option to throw an error inside the map function ?

Screen Shot 2020-03-11 at 22 37 18

Hi @RahavLussato. BrightFutures uses typed errors and therefore doesn't directly work with Swift's untyped throws. The alternative is to use the flatMap variant that allows you to return a Result: https://github.com/Thomvis/BrightFutures/blob/master/Sources/BrightFutures/AsyncType+ResultType.swift#L72.

Thanks @Thomvis , can you help me how should i write this ?
i tried like this but its not compiling, "Cannot invoke 'flatMap' with an argument list of type '(@escaping (JSON) -> Result)'"

return client.call(method: method, params: json).flatMap { (json:JSON) -> Result<JSON> in
                var result: Result<JSON, Error>
                
                do {
                    let response = try self.decoder.decode(responseType, from: json.rawData())
                    DDLogDebug("call process \(json)")
                    result = response
                }
                catch let error {
                    DDLogError("Parse \(method) response failed: \(json) with error \(error.localizedDescription)")
                    result = error
                }
                
                return result
            }

A couple of things:

  • the result type of your closure is defined as Result<JSON> but should be Result<JSON, Error>
  • when you assign response to result, you need to use the correct result enum case, so result = .success(response)
  • same goes for the error case (wrap it in .failure)

Thanks @Thomvis but still getting errors :(

  1. Cannot invoke 'flatMap' with an argument list of type '(@escaping (JSON) -> <>)'
  2. Generic type 'Result' specialized with too many type parameters (got 2, but expected 1)
return client.call(method: method, params: json).flatMap { (json:JSON) -> Result<JSON, Error> in
                var result: Result<JSON, Error>
                
                do {
                    let response = try self.decoder.decode(responseType, from: json.rawData())
                    DDLogDebug("call process \(json)")
                    result = .success(response)
                }
                catch let error {
                    DDLogError("Parse \(method) response failed: \(json) with error \(error.localizedDescription)")
                    result = .failure(response)
                }
                
                return result
            }

It seems like the compiler is confused about which Result type to use. Do you or any of your dependencies declare one with a single type parameter?

nothing that I can find, can I specify it?

now it compiled :)

return client.call(method: method, params: json).flatMap { (json:JSON) -> Swift.Result<T, Error> in
                var result: Swift.Result<T, Error>
                
                do {
                    let response = try self.decoder.decode(responseType, from: json.rawData())
                    DDLogDebug("call process \(json)")
                    result = .success(response)
                }
                catch let error {
                    DDLogError("Parse \(method) response failed: \(json) with error \(error.localizedDescription)")
                    result = .failure(error)
                }
                
                return result
            }

@Thomvis so does it going to return to the right callback (onSuccess / onFailure) by the type of the result ?