The motivation for this idea is that it would be nice if the happy path didn't need to gain a level of indentation just because we want to do some error handling. A solution that occurs to me is the following:
readFromDatabase() catch {
tx.rollback()
}
One can attach a catch block directly to the end of a throwing expression (readFromDatabase() in this example is a throwing operation), and doing so also means that we don't need to write try on readFromDatabase(), since the control flow can no longer be broken by a thrown error.
It is debatable whether or not try should be required if an error is thrown from the catch block, e.g.:
Without try it could look to the casual reader like try tx.rollback() is somehow contained and that the whole expression can't exit the containing function by throwing an error.
Oh, this post was a bit off the cuff, and thinking about it just a bit more I realize that my example function readFromDatabase() would presumably return a value, and it’s not clear how return values should be handled in my proposed syntax. So… this post has been demoted to “food for thought”
Yes, this is my idea - I started off thinking just as you did, and then I too realized that do is unnecessary, and then I realized that if all thrown errors are caught then we don’t need try either
Something similar can be achieved right now using Result:
let result = Result { try readFromDatabase() }
guard case let .success(value) = result else {
tx.rollback()
return
}
// Un-nested happy path with unwrapped value
print(value)
It might be a nice quality of life thing to consider adding some Optional unwrapping like syntax sugar for this though:
guard try let value = readFromDatabase() else {
tx.rollback()
return
}
print(value)
Might make error handling look nicer than it currently is?
While that does work, it loses the actual error value from the function call since try? converts it to an optional, which isn’t ideal for error propagation.
Yeah, I'd love to be able to use statement expressions in more places, but I think if that's even on the table then it'd have to be added in a new major version and staged in as an upcoming feature.