<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Mar 10, 2017, at 9:49 AM, Joe Groff via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">Having&nbsp;ExpressibleByStringInterpolation refine&nbsp;ExpressibleByStringLiteral makes sense. I think there's a more powerful alternative design you should also consider. If the protocol looked like this:<div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class="">protocol ExpressibleByStringInterpolation: ExpressibleByStringLiteral {</div><div class="">&nbsp; associatedtype LiteralSegment: ExpressibleByStringLiteral</div><div class="">&nbsp; associatedtype InterpolatedSegment</div><div class="">&nbsp; init(forStringInterpolation: Void)</div><div class=""><br class=""></div><div class="">&nbsp; mutating func append(literalSegment: LiteralSegment)</div><div class="">&nbsp; mutating func append(interpolatedSegment: InterpolatedSegment)</div><div class="">}</div></blockquote><div class=""><br class="">Then an interpolation expression like this in `Thingy` type context:<br class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class="">"foo \(bar) bas \(zim: 1, zang: 2)\n"</div></blockquote><div class=""><br class=""></div><div class="">could desugar to something like:<br class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class="">{</div><div class="">&nbsp; var x = Thingy(forStringInterpolation: ())</div><div class="">&nbsp; // Literal segments get appended using append(literalSegment: "literal")</div><div class="">&nbsp; x.append(literalSegment: "foo ")</div><div class="">&nbsp; // \(...) segments are arguments to a InterpolatedSegment constructor</div><div class="">&nbsp; x.append(interpolatedSegment: Thingy.InterpolatedSegment(bar))</div><div class="">&nbsp; x.append(literalSegment: " bas ")</div><div class="">&nbsp; x.append(interpolatedSegment: Thingy.InterpolatedSegment(zim: 1, zang: 2))</div><div class=""><br class=""></div><div class="">&nbsp; return x</div><div class="">}()</div></blockquote><div class=""><br class=""></div><div class="">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.</div></div></div></blockquote><div><br class=""></div><div>Hi Joe,</div><div><br class=""></div><div>The trade-offs for this approach would be:</div><div>- each append would need to return a valid object w.r.t the type’s invariants.</div><div>- an implementation could use the init(stringInterpolation:) could be a final building step, while append would not indicate that the object construction was complete.&nbsp;</div><div><br class=""></div><div>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.</div><div><br class=""></div><div>-DW</div></div><br class=""></body></html>