What on Earth is a recoverable precondition? Isn’t the point of a precondition to be non-recoverable?

Yes. Sorry I couldn’t think of a better name1.

The Result

/// Checks a necessary condition for making forward progress.
/// The difference with `precondition` is that if an error is _thrown_ when the condition is executed, the error will
/// be _rethrown_ so that it can be recovered. But this recoverability does not apply if the condition executes
/// properly and its condition fails.
/// In other words, this function is a wrapper around `precondition` so that it can be fed a condition closure that can
/// throw.
func recoverablePrecondition(
    _ condition: @autoclosure () throws -> Bool,
    _ message: @autoclosure () -> String = String(),
    file: StaticString = #file,
    line: UInt = #line
) rethrows {
    if !(try condition()) {
        preconditionFailure(message(), file: file, line: line)

What is this?

Let me explain. Here is the code I had:


But then, I had to make aLittleTenderness able to throw, and precondition was yelling at me about it:

Property access can throw, but it is not marked with 'try' and it is executed in
a non-throwing autoclosure

Even when I tried a little tenderness2:

precondition(try aLittleTenderness())

The compiler would complain:

Property access can throw, but it is executed in a non-throwing autoclosure

And this alternative looked terrible:

precondition((try? aLittleTenderness()) ?? false)

So I created a recoverable precondition, which means:

  • if the code throws, then try to recover from it;
  • if the code does not throw, treat it as a precondition.

Don’t hate me. Listen to soul music instead.

Lessons Learned

Look at this badass signature! Of course I started from the signature of precondition and I adapted it to my needs. It features some keywords I don’t use everyday. Each keyword deserves its own extensive explanation. But wait, other people have already written about them:

  1. If you can think of one, let me know.

  2. Beware, a terrible music joke is hiding in this statement, can you spot it?