Last active
November 13, 2016 19:00
-
-
Save damianesteban/a697ab5a2af38c7890760382a2e38c06 to your computer and use it in GitHub Desktop.
Swift 3 updated code with simple examples from this fantastic article: http://alisoftware.github.io/swift/async/error/2016/02/06/async-errors/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// A Gist. | |
struct Gist { | |
let id: String | |
} | |
typealias JSONDictionary = [String: AnyObject] | |
// These methods are "helpers" to transform Data -> JSON -> Result<[Gist]> | |
func jsonFrom(data: Data) -> Result<AnyObject> { | |
let json = try! JSONSerialization.jsonObject(with: data, options: []) | |
return Result.success(json as AnyObject) | |
} | |
func gistFrom(json: JSONDictionary) -> Gist { | |
let id = json["id"] as! String | |
return Gist(id: id) | |
} | |
func gistsFrom(json: AnyObject) -> Result<[Gist]> { | |
let gistsJSON = json as! [JSONDictionary] | |
let gists = gistsJSON.flatMap { gistFrom(json: $0) } | |
return Result.success(gists) | |
} | |
// Result Type w/ extensions | |
enum Result<T> { | |
case success(T) | |
case failure(Error) | |
} | |
extension Result { | |
func map<U>(f: (T) -> U) -> Result<U> { | |
switch self { | |
case .success(let t): return .success(f(t)) | |
case .failure(let error): return .failure(error) | |
} | |
} | |
func flatMap<U>(f: (T) -> Result<U>) -> Result<U> { | |
switch self { | |
case .success(let t): return f(t) | |
case .failure(let error): return .failure(error) | |
} | |
} | |
} | |
extension Result { | |
// Return the value if it is a .success or throw the error if it is a .failure | |
func resolve() throws -> T { | |
switch self { | |
case Result.success(let value): return value | |
case Result.failure(let error): throw error | |
} | |
} | |
// Construct a .success if the expression returns a value or a .failure if it throws | |
init( _ throwingExpression: (Void) throws -> T) { | |
do { | |
let value = try throwingExpression() | |
self = Result.success(value) | |
} catch { | |
self = Result.failure(error) | |
} | |
} | |
} | |
// Error Type | |
enum GistError: Error { | |
case badData(Data) | |
} | |
let url = URL(string: "https://api.github.com/gists/public")! | |
fetch(url: url) { (resultData: Result<Data>) in | |
let resultGists = resultData | |
.flatMap(f: jsonFrom) | |
.flatMap(f: gistsFrom) | |
// Then if we want to go back in the do/try/catch world for the rest of the code: | |
do { | |
let gists = try resultGists.resolve() | |
} catch { | |
print("error") | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment