> On Mar 10, 2017, at 11:27 AM, David Waite <[email protected]>
> wrote:
>
>>
>> On Mar 10, 2017, at 9:49 AM, Joe Groff via swift-evolution
>> <[email protected]> wrote:
>>
>> Having ExpressibleByStringInterpolation refine ExpressibleByStringLiteral
>> makes sense. I think there's a more powerful alternative design you should
>> also consider. If the protocol looked like this:
>>
>> protocol ExpressibleByStringInterpolation: ExpressibleByStringLiteral {
>> associatedtype LiteralSegment: ExpressibleByStringLiteral
>> associatedtype InterpolatedSegment
>> init(forStringInterpolation: Void)
>>
>> mutating func append(literalSegment: LiteralSegment)
>> mutating func append(interpolatedSegment: InterpolatedSegment)
>> }
>>
>> Then an interpolation expression like this in `Thingy` type context:
>>
>> "foo \(bar) bas \(zim: 1, zang: 2)\n"
>>
>> could desugar to something like:
>>
>> {
>> var x = Thingy(forStringInterpolation: ())
>> // Literal segments get appended using append(literalSegment: "literal")
>> x.append(literalSegment: "foo ")
>> // \(...) segments are arguments to a InterpolatedSegment constructor
>> x.append(interpolatedSegment: Thingy.InterpolatedSegment(bar))
>> x.append(literalSegment: " bas ")
>> x.append(interpolatedSegment: Thingy.InterpolatedSegment(zim: 1, zang: 2))
>>
>> return x
>> }()
>>
>> This design should be more efficient, since there's no temporary array of
>> segments that needs to be formed for a variadic argument, you don't need to
>> homogenize everything to Self type up front, and the string can be built up
>> in-place. It also provides means to address problems 3 and 4, since the
>> InterpolatedSegment associated type can control what types it's
>> initializable from, and can provide initializers with additional arguments
>> for formatting or other purposes.
>
> Hi Joe,
>
> The trade-offs for this approach would be:
> - each append would need to return a valid object w.r.t the type’s invariants.
> - an implementation could use the init(stringInterpolation:) could be a final
> building step, while append would not indicate that the object construction
> was complete.
> One example where this could be a problem would be if someone used the
> segments to build up a localized representation of the interpolated string.
Validation is a general problem with the literal protocols, since none of the
literal protocols allow for failed initialization, and if you can write "foo
\(bar) bas", you can write "foo " or "foo \(bar)", so you need to have a
representation for those intermediate states already. I think allowing the
literal and interpolated types to be different is important. You could achieve
that with an initializer that took a variadic list of enums, perhaps:
protocol ExpressibleByStringInterpolation: ExpressibleByStringLiteral {
associatedtype LiteralSegment: ExpressibleByStringLiteral
associatedtype InterpolatedSegment
enum Segment { case literal(LiteralSegment),
interpolated(InterpolatedSegment) }
init(stringInterpolation: Segment...)
}
That still requires the argument array to be constructed up front, though.
-Joe
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution