Swift Tip: From Optionals to Errors
When working with optional values it's common to check for nil
using a guard statement. In cases where the value is not present this results in an early exit. Using an example from our recently open-sourced Swift Talk backend, we often write code that throws an error in the nil
case:
guard let gift = g else {
throw ServerError(privateMessage: "No such gift")
}
// ... rest of the code that uses `gift`
There are many reasons we could run into a nil
value; the user might enter an invalid URL, for example, or the database connection might fail. When we encounter nil
, we leave the happy path and have to exit early.
Since this pattern repeats itself in a number of places throughout our codebase, we can write an extension on Optional
that abstracts this pattern away:
extension Optional {
func or(_ err: Error) throws -> Wrapped {
guard let value = self else {
throw err
}
return value
}
}
Using this extension, we can write our initial example like this:
let gift = try g.or(ServerError(privateMessage: "No such gift"))
We could also choose to use a custom operator, which might stand out more when reading the code:
infix operator ?!: NilCoalescingPrecedence
public func ?!<A>(lhs: A?, rhs: Error) throws -> A {
guard let value = lhs else {
throw rhs
}
return value
}
The NilCoalescingPrecedence
group specifies that our new operator has the same precedence as ??
.
Using this operator, the example now looks like this:
let gift = try g ?! ServerError(privateMessage: "No such gift")
We find that small abstractions of common patterns can remove some of the noise from our code, making it more readable overall.
For those instances where you care less about the specific error message, you could try creating a postfix operator, similar to the one used for force-unwrapping.
To learn more about our Swift Talk backend, watch the first episode of our latest series, or check out the full source code on GitHub.
Our book, Advanced Swift, discusses Optionals and error handling in more depth. We're preparing an update for Swift 5, free for all Ebook readers. ๐