Skip to content

Instantly share code, notes, and snippets.

@damianesteban
Last active November 13, 2016 19:00
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save damianesteban/a697ab5a2af38c7890760382a2e38c06 to your computer and use it in GitHub Desktop.
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/
// 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