Created
October 29, 2015 23:46
-
-
Save marcoconti83/0e62e5986153334b9934 to your computer and use it in GitHub Desktop.
Guard-catch in swift?
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 characters
| /** | |
| # QUESTION | |
| Is there a way to combine `guard` and `try-catch`, so that we can | |
| exploit the `guard let` to have a immutable value, but have an early | |
| return in case of errors? | |
| */ | |
| import Foundation | |
| /// Very obscure errors | |
| enum ObscureError : ErrorType { | |
| case DisturbanceInTheForce | |
| case TimeDilationAnomaly | |
| } | |
| enum ComputationError : ErrorType { | |
| case Error(_: String) | |
| } | |
| /// A very unstable function | |
| func blackBox() throws -> UInt32 { | |
| guard arc4random_uniform(6) != 3 else { throw ObscureError.DisturbanceInTheForce } | |
| guard arc4random_uniform(6) != 1 else { throw ObscureError.TimeDilationAnomaly } | |
| return arc4random_uniform(6) | |
| } | |
| /** | |
| # SOLUTION 1 | |
| Use `var`s, and assign to them them inside a `do-catch` | |
| ## PROS: | |
| - We can distinguish between `DisturbanceInTheForce` and `TimeDilationAnomaly` | |
| ## CONS: | |
| - `foo` has to be a `var` even if it should be a `let` | |
| */ | |
| func compute1() throws { | |
| var foo1 : UInt32 | |
| var foo2 : UInt32 | |
| do { | |
| foo1 = try blackBox() | |
| } | |
| catch ObscureError.DisturbanceInTheForce { | |
| throw ComputationError.Error("a") | |
| } | |
| catch ObscureError.TimeDilationAnomaly { | |
| throw ComputationError.Error("b") | |
| } | |
| do { | |
| foo2 = try blackBox() | |
| } | |
| catch ObscureError.DisturbanceInTheForce { | |
| throw ComputationError.Error("c") | |
| } | |
| catch ObscureError.TimeDilationAnomaly { | |
| throw ComputationError.Error("d") | |
| } | |
| // ... some calculation that uses foo1 and foo2 ... | |
| print("\(foo1+foo2)") | |
| } | |
| /** | |
| # SOLUTION 2 | |
| Use `let` inside nested `do-catch`es | |
| ## PROS: | |
| - We can distinguish between `DisturbanceInTheForce` and `TimeDilationAnomaly` | |
| - `foo` is a let | |
| ## CONS: | |
| - Readability issue | |
| - Quickly degenerates into a Pyramid of Doom | |
| */ | |
| func compute2() throws { | |
| do { | |
| let foo1 = try blackBox() | |
| do { | |
| let foo2 = try blackBox() | |
| // ... some calculation that uses foo1 and foo2 ... | |
| print("\(foo1+foo2)") | |
| } | |
| catch ObscureError.DisturbanceInTheForce { | |
| throw ComputationError.Error("c") | |
| } | |
| catch ObscureError.TimeDilationAnomaly { | |
| throw ComputationError.Error("d") | |
| } | |
| } | |
| catch ObscureError.DisturbanceInTheForce { | |
| throw ComputationError.Error("a") | |
| } | |
| catch { | |
| throw ComputationError.Error("b") | |
| } | |
| } | |
| /** | |
| # SOLUTION 3 | |
| Use a `guard` and a optional `try` to d | |
| PROS: | |
| - Extremely readable and concise | |
| - `foo` is a `let` | |
| CONS: | |
| - Can't distinguish between errors. Is it a `DisturbanceInTheForce` or a `TimeDilationAnomaly`? | |
| */ | |
| func compute3() throws { | |
| guard let foo1 = try? blackBox() else { throw ComputationError.Error("a or b") } | |
| guard let foo2 = try? blackBox() else { throw ComputationError.Error("c or d") } | |
| // ... some calculation that uses foo1 and foo2 ... | |
| print("\(foo1+foo2)") | |
| } | |
| /** | |
| # SOLUTION 4 | |
| Hypothetical `guard-catch` construct | |
| PROS: | |
| - Readable | |
| - `foo` is a `let` | |
| CONS: | |
| - Not supported in Swift :) | |
| */ | |
| /* | |
| func compute4() throws { | |
| guard let foo1 = try blackBox() | |
| catch ObscureError.DisturbanceInTheForce { | |
| ComputationError.Error("a") | |
| } | |
| catch { | |
| ComputationError.Error("b") | |
| } | |
| guard let foo2 = try blackBox() | |
| catch ObscureError.DisturbanceInTheForce { | |
| ComputationError.Error("c") | |
| } | |
| catch { | |
| ComputationError.Error("d") | |
| } | |
| // ... some calculation that uses foo1 and foo2 ... | |
| print("\(foo1+foo2)") | |
| } | |
| */ |
SOLUTION 1 can be:
let foo1: UInt32?
let foo2: UInt32?
do {
// binding it here...
} catch {
// initialize A nil here ...
}
do ... catch ... so on...
It really can be LET, tediously.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I wish it got implemented. http://thread.gmane.org/gmane.comp.lang.swift.evolution/8266