Adding nil coalescing to result

It’s not rare to have code that uses Swift’s Result in a simplified way. Not all call sites need to handle the error and may choose to throw the error away, opting instead to provide a default value. There are a many ways to achieve this goal - here’s three alternate spellings to achieve the same thing:

let deliveryStatus: String

switch lookupDeliveryStatus() {
case let .success(value):
    deliveryStatus = value
case .failure:
    deliveryStatus = "In progress..."
}

Or

let deliveryStatus: String

if case let .success(value) = lookupDeliveryStatus() {
    deliveryStatus = value
} else {
    deliveryStatus = "In progress..."
}

Or

let deliveryStatus = (try? lookupDeliveryStatus().get()) ?? "In progress..."

The last example is pretty short but it’s quite noisy with a try? that is wrapped in () and then a usage of the nil-coalescing operator (??). We can reduce a lot of the noise by defining an implementation of the nil-coalescing operator on the Result type directly.

extension Result {
    public static func ?? (result: Result, defaultValue: @autoclosure () throws -> Success) rethrows -> Success {
        switch result {
        case .success(let value):
            return value
        case .failure:
            return try defaultValue()
        }
    }
}

With this in place our original example becomes much more succinct

let deliveryStatus = lookupDeliveryStatus() ?? "In progress..."

The above felt a little uncomfortable to begin with because the thing returning a Result obviously felt it was important enough to provide some additional context in the event of a failure so surely we should pay attention to it. I think this tension is interesting as it causes a pause to consider whether you really should be handling the error or are happy to ignore it.

Something that eases the tension for me is that the actual implementation is a copy/paste/tweak job from the function defined to work on optionals, so there is prior art that it’s reasonable to provide a convenience for this operation.