SE-0477: Default Value in String Interpolations

I'm all in favor of this as a tactical solution to the optional interpolation problem. But I wanted to float a more general solution, for completeness:

The addition of an Either type into the standard library is a generally useful idea. The big win for such a nominal type is that you can give it protocol conformances for when both the underlying types conform, e.g.

enum Either<Left, Right> {
    case left(Left)
    case right(Right)
}

extension Either: CustomStringConvertible
where Left: CustomStringConvertible,
      Right: CustomStringConvertible
{
  var description: String {
    switch self {
    case let .left(l): return l.description
    case let .right(r): return r.description
    }
  }
}

This is especially useful for things like when you want to return one of two different collection types. An Either conforming to Collection is vastly more performant that any Collection or AnyCollection.

Why this is relevant here is you can define a cousin to the ?? operator, ?|, the "nil alternative operator:

infix operator ?|: NilCoalescingPrecedence

func ?|<L, R>(_ maybe: L?, _ or: @autoclosure ()->R) -> Either<L, R> {
    switch maybe {
    case let l?: .left(l)
    case nil: .right(or())
    }
}

Unlike ??, the right-hand side is not of the wrapped type, but of an arbitrary type.

This can then be used to solve things like string-interpolating an optional with a default value:

    let maybeInt: Int? = Int("x")
    print("\(maybeInt ?| "<nil>")") // prints "<nil>"

Is this better than the more targeted solution here? Probably not, but I think this kind of operator, and Either more broadly, has a lot of general utility and this is one example of that.

34 Likes