Nevin
1
SE–0228: Fix ExpressibleByStringInterpolation made it possible to have string interpolations with labels and multiple parameters. The proposal’s examples include an HTML type which accepts interpolations like:
let x: HTML = "\(url: origin, withAllowedCharacters: .urlQueryAllowed)"
However, sometimes I want to add interpolations like that to an existing type. For example, String has an initializer that takes an integer and radix:
let s = String(n, radix: 16)
I would like to be able to write \(n, radix: 16) as an interpolation within a larger string. In particular, I do not want to write \(String(n, radix: 16)).
I tried adding appendInterpolation(_:radix:) as a mutating function in an extension of String, but I get a compile-time error when I try to use it.
Is there a way that I can make this work?
String uses DefaultStringInterpolation. You need to add appendInterpolation there:
extension DefaultStringInterpolation {
mutating func appendInterpolation(_ n: Int, radix: Int) {
appendLiteral(String(n, radix: radix))
}
}
The caveat is that all types using this interpolation scheme will be affected (which is more-or-less expected).
Edit:
You can also add it to any interpolation scheme with String as a literal type, but I doubt it’d be any more useful:
extension StringInterpolationProtocol where StringLiteralType == String {
...
}
3 Likes
That option is probably ill‐advised. One of the main reasons to create and use a conformer besides DefaultStringInterpolation is in order to restrict the available interpolations at compile time as a correctness aid in a particular situation. By extending every such type wholesale, you may be shooting yourself in the foot. Instead I would create a new protocol that refines it, and conform whatever interpolation engines you care about to that protocol:
protocol RadixInterpolation: StringInterpolationProtocol where StringLiteralType == String {}
extension RadixInterpolation {
mutating func appendInterpolation(_ n: Int, radix: Int) {
// ...
}
}
extension DefaultStringInterpolation: RadixInterpolation {}
extension HelpfulInterpolation: RadixInterpolation {}
extension CustomInterpolation: RadixInterpolation {}
extension MyInterpolation: RadixInterpolation {}
// But no extension to `StrictInterpolation` or `SafeInterpolation`,
// because that would be counterproductive.
Edit: On the other hand, I guess if the extension isn’t public anyway, and you don’t expect to use a safety interpolator anywhere in your own code, then the extra effort probably isn’t worth it.
4 Likes