If I’ve got a bunch of chained guard let statements, how can I diagnose which condition failed, short of breaking apart my guard let into multiple statements?
Given
I wish I had a good answer for that but I have not.
However let's take a look at the problem together. This is a simplified version of your function
func foo(dictionary:[String:AnyObject]) -> AnyObject? {
guard let
a = dictionary["a"] as? String,
b = dictionary[a] as? String,
c = dictionary[b] else {
return nil // I want to know more ☹️ !!
}
return c
}
First of all inside the else
block we do NOT have access to the constants defined in the guard
statement. This because the compiler doesn't know which one of the clauses did fail. So it does assume the worst case scenario where the first clause did fail.
Conclusion: we cannot write a "simple" check inside the else
statement to understand what did not work.
Of course we could replicate inside the else
the logic we put insito the guard statement to find out the clause which did fail but this boilerplate code is very ugly and not easy to maintain.
So yes, we need to split the guard statement. However if we want a more detailed information about what did go wrong our foo
function should no longer return a nil
value to signal an error, it should throw an error instead.
So
enum AppError: ErrorType {
case MissingValueForKey(String)
}
func foo(dictionary:[String:AnyObject]) throws -> AnyObject {
guard let a = dictionary["a"] as? String else { throw AppError.MissingValueForKey("a") }
guard let b = dictionary[a] as? String else { throw AppError.MissingValueForKey(a) }
guard let c = dictionary[b] else { throw AppError.MissingValueForKey(b) }
return c
}
I am curious about what the community thinks about this.