Last active
August 16, 2016 10:42
Revisions
-
BlameOmar revised this gist
Sep 8, 2015 . 1 changed file with 2 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -92,9 +92,9 @@ findAnswerToTheUltimateQuestion { result in dispatch_async(dispatch_get_main_queue()) { print(answer); } } catch let error { dispatch_async(dispatch_get_main_queue()) { print(error); } } } -
BlameOmar revised this gist
Sep 8, 2015 . 1 changed file with 6 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -89,9 +89,13 @@ Here's how this function might be used: findAnswerToTheUltimateQuestion { result in do { let answer = try result.unwrap() dispatch_async(dispatch_get_main_queue()) { print(answer); } } catch let e { dispatch_async(dispatch_get_main_queue()) { print(e); } } } ``` -
BlameOmar revised this gist
Sep 8, 2015 . 1 changed file with 4 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -65,7 +65,10 @@ Here's an example of how an asynchronous library function might be implemented: ```swift func findAnswerToTheUltimateQuestion(completion: (Result<Int>) -> ()) { //Computers are much faster today than they were in 1978, so this only takes a week let latency: Int64 = 1000*1000*1000*60*60*24*7; let time = dispatch_time(DISPATCH_TIME_NOW, latency); dispatch_after(time, dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0)) { let result = Result { //any number of statements that may potentially throw return 42; -
BlameOmar revised this gist
Sep 8, 2015 . 1 changed file with 18 additions and 8 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -11,13 +11,15 @@ Swift 2.0 introduces throwable errors, which are similar to exceptions. However propogate only down the call stack and can only be caught in the same thread that threw them. In order to propogate the errors upwards (such as to callback routines) and across thread boundaries it is necessary to catch the errors and pass them along in some sort of instantiable type, and however this is done, it is preferable to be able to later handle those errors the same way as all other thrown errors. One way to do this is through a thowing closure that either returns a value or thows an error, as detailed in [this blog post](http://appventure.me/2015/06/19/swift-try-catch-asynchronous-closures/). However, this strikes me as odd as a closure can do anything and the desired behavior is very well defined. Through a simple extension to the familiar Result enum can serve this purpose. First here is the definition of a typical Result enum: ```swift enum Result<T: Any> { @@ -26,7 +28,11 @@ enum Result<T: Any> { } ``` Many versions of the Result enum use NSError for the failure case, or accept a second type parameter for the failure case. ErrorType is a new protocol introduced in Swift 2.0 that all throwable errors, including NSError conform to. Here is the extension to Result: ```swift extension Result { @@ -54,7 +60,7 @@ The unwrap method returns the value for ```swift .Success``` and throws the erro The initializer provides a convenient way to create a Result object for an arbitary block of code, simplifying the implementation of asynchronous functions. Here's an example of how an asynchronous library function might be implemented: ```swift func findAnswerToTheUltimateQuestion(completion: (Result<Int>) -> ()) { @@ -70,7 +76,11 @@ func findAnswerToTheUltimateQuestion(completion: (Result<Int>) -> ()) { } ``` Thanks to type inference, there is no need to specify the type for the success case. If it weren't for syntax coloring and the capitalization of the R, it may not be apparent at a glance that Result isn't simply a language level construct. Here's how this function might be used: ```swift findAnswerToTheUltimateQuestion { result in -
BlameOmar revised this gist
Sep 8, 2015 . 1 changed file with 2 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -4,7 +4,7 @@ As Swift 1.0 did not include support for exceptions, a common error handling pat that either took on a value on success, or an error on failure. In a way, this was superior to using exceptions, since being a instantiable type, Results could be passed around freely, enabling asynchronous code to use the same error handling mechanisim as synchronous code. Using Swift's robust support for custom operators, this also enabled [Railway Oriented Programming](http://fsharpforfunandprofit.com/posts/recipe-part2/) for more functional oriented programers. Swift 2.0 introduces throwable errors, which are similar to exceptions. However, like exceptions, thrown errors @@ -13,7 +13,7 @@ the errors upwards (such as to callback routines) and across thread boundaries i and pass them along in some sort of instantiable type, and however this is done, it is preferable to be able to later handle those errors the same way as all other thrown errors. One way to do this is through a thowing closure that either returns a value or thows an error, as detailed in [this blog post](http://appventure.me/2015/06/19/swift-try-catch-asynchronous-closures/). However, this strikes me as odd as a closure can do anything and the desired behavior is very well defined. Through a simple extension to the familiar Result enum can serve this purpose. -
BlameOmar revised this gist
Sep 8, 2015 . 1 changed file with 11 additions and 3 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -4,10 +4,18 @@ As Swift 1.0 did not include support for exceptions, a common error handling pat that either took on a value on success, or an error on failure. In a way, this was superior to using exceptions, since being a instantiable type, Results could be passed around freely, enabling asynchronous code to use the same error handling mechanisim as synchronous code. Using Swift's robust support for custom operators, this also enabled [http://fsharpforfunandprofit.com/posts/recipe-part2/](Railway Oriented Programming) for more functional oriented programers. Swift 2.0 introduces throwable errors, which are similar to exceptions. However, like exceptions, thrown errors propogate only down the call stack and can only be caught in the same thread that threw them. In order to propogate the errors upwards (such as to callback routines) and across thread boundaries it is necessary to catch the errors and pass them along in some sort of instantiable type, and however this is done, it is preferable to be able to later handle those errors the same way as all other thrown errors. One way to do this is through a thowing closure that either returns a value or thows an error, as detailed in [http://appventure.me/2015/06/19/swift-try-catch-asynchronous-closures/](this blog post). However, this strikes me as odd as a closure can do anything and the desired behavior is very well defined. Through a simple extension to the familiar Result enum can serve this purpose. First we start with the familiar Result type: -
BlameOmar revised this gist
Sep 8, 2015 . 1 changed file with 16 additions and 6 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -1,8 +1,15 @@ # Asynchronous Error Handling in Swift 2.0 As Swift 1.0 did not include support for exceptions, a common error handling pattern was to use a Result enum that either took on a value on success, or an error on failure. In a way, this was superior to using exceptions, since being a instantiable type, Results could be passed around freely, enabling asynchronous code to use the same error handling mechanisim as synchronous code. Using Swift's robust support for custom operators, this also enabled [http://fsharpforfunandprofit.com/posts/recipe-part2/](Railway Oriented Programming) for more functional oriented programers. Swift 2.0 introduces throwable errors, which are similar to exceptions. However, like exceptions, thrown errors can only be caught in the same thread that threw them. First we start with the familiar Result type: ```swift enum Result<T: Any> { @@ -38,7 +45,8 @@ extension Result { The unwrap method returns the value for ```swift .Success``` and throws the error for ```swift .Failure```. The initializer provides a convenient way to create a Result object for an arbitary block of code, simplifying the implementation of asynchronous functions. Example: ```swift func findAnswerToTheUltimateQuestion(completion: (Result<Int>) -> ()) { @@ -54,11 +62,13 @@ func findAnswerToTheUltimateQuestion(completion: (Result<Int>) -> ()) { } ``` ```swift findAnswerToTheUltimateQuestion { result in do { let answer = try result.unwrap() //Do something with the answer } catch let e { print(e) } -
BlameOmar revised this gist
Sep 8, 2015 . 1 changed file with 22 additions and 8 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -1,4 +1,8 @@ # Asynchronous Error Handling in Swift 2.0 TODO: Write introduction First we start with the familiar, de facto standard Result type: ```swift enum Result<T: Any> { @@ -7,7 +11,7 @@ enum Result<T: Any> { } ``` Next, we add a simple extension: ```swift extension Result { @@ -31,16 +35,26 @@ extension Result { } ``` The unwrap method returns the value for ```swift .Success``` and throws the error for ```swift .Failure```. The initializer provides a convenient way to create a Result object for an arbitary block of code, simplifying the implementation of asynchronous functions. For example: ```swift func findAnswerToTheUltimateQuestion(completion: (Result<Int>) -> ()) { //Computers are much faster today than they were in 1978, so this only takes a week dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1000*1000*1000*60*60*24*7), dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0)) { let result = Result { //any number of statements that may potentially throw return 42; } completion(result); } } ``` ```swift doSomethingAsynchronously { result in do { let x = try result.unwrap() -
BlameOmar renamed this gist
Sep 8, 2015 . 1 changed file with 0 additions and 0 deletions.There are no files selected for viewing
File renamed without changes. -
BlameOmar renamed this gist
Sep 8, 2015 . 1 changed file with 11 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -1,8 +1,15 @@ First we start with the de facto standard Result type ```swift enum Result<T: Any> { case Success(T) case Failure(ErrorType) } ``` Next, we add a simple extension ```swift extension Result { init(_ f: () throws -> T) { @@ -22,7 +29,9 @@ extension Result { } } } ``` ```swift func doSomethingAsynchronously(completion: (Result<Int>) -> ()) { let result = Result { //any number of statements that may potentially throw @@ -39,4 +48,5 @@ doSomethingAsynchronously { result in } catch let e { print(e) } } ``` -
BlameOmar created this gist
Sep 8, 2015 .There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,42 @@ enum Result<T: Any> { case Success(T) case Failure(ErrorType) } extension Result { init(_ f: () throws -> T) { do { self = .Success(try f()) } catch let e { self = .Failure(e) } } func unwrap() throws -> T { switch self { case let .Success(x): return x case let .Failure(e): throw e } } } func doSomethingAsynchronously(completion: (Result<Int>) -> ()) { let result = Result { //any number of statements that may potentially throw return 42; } completion(result); } doSomethingAsynchronously { result in do { let x = try result.unwrap() //do something with x } catch let e { print(e) } }