Blog
Blog copied to clipboard
A practical use for guard statements
Maybe it's written already somewhere, but I only took notice of this just now. I originally looked at guard statements as just sugar for inverted if statements that only look good, but don't protect you from bugs. I had the following bug in a PR:
func foo(completionHandler: @escaping (Result<...>) -> Void) {
bar { values in
if things.isEmpty {
completion(.failure(.someError))
}
completion(.success(values))
}
}
A colleague pointed out that I may be missing a return
after calling the completion handler in the body of the if statement above, unless I intend to call the completion handler with success right after calling it with failure which seems unlikely.
This was an eye-opener for me. Had I used a guard statement, I would have been forced to insert a return statement; and thus saving me from a bug.
func foo(completionHandler: @escaping (Result<...>) -> Void) {
bar { values in
guard !things.isEmpty else {
completion(.failure(.someError))
return
}
completion(.success(values))
}
}
To be honest, I always used guard
s to "sanitize" my code path, keeping failures and exception handling in the else block of the guard(s) in that code, but when the code after the guard was just a single line I tended to turn it to an if for no clear reason, but no more 😉