<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 Jan 20, 2017, at 8:28 AM, Dave Abrahams via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="content-type" content="text/html; charset=utf-8" class=""><div dir="auto" class=""><div class=""><span class=""></span></div><div class=""><span class=""></span><br class=""><span class=""></span><br class=""><span class="">Sent from my iPad</span><br class=""><span class=""></span><br class=""><div class=""><br class=""><br class="">Sent from my iPad</div><blockquote type="cite" class=""><span class="">On Jan 20, 2017, at 5:48 AM, Jonathan Hull <<a href="mailto:jhull@gbis.com" class="">jhull@gbis.com</a>> wrote:</span><br class=""></blockquote><blockquote type="cite" class=""><span class=""></span><br class=""></blockquote><blockquote type="cite" class=""><span class="">Thanks for all the hard work!</span><br class=""></blockquote><blockquote type="cite" class=""><span class=""></span><br class=""></blockquote><blockquote type="cite" class=""><span class="">Still digesting, but I definitely support the goal of string processing even better than Perl. Some random thoughts:</span><br class=""></blockquote><blockquote type="cite" class=""><span class=""></span><br class=""></blockquote><blockquote type="cite" class=""><span class="">• I also like the suggestion of implicit conversion from substring slices to strings based on a subtype relationship, since I keep running into that issue when trying to use array slices. </span><br class=""></blockquote><span class=""></span><br class=""><span class="">Interesting. Could you offer some examples?</span><br class=""><span class=""></span><br class=""><blockquote type="cite" class=""><span class="">It would be nice to be able to specify that conversion behavior with other types that have a similar subtype relationship.</span><br class=""></blockquote><span class=""></span><br class=""><span class="">Indeed.</span><br class=""><span class=""></span><br class=""><blockquote type="cite" class=""><span class="">• One thing that stood out was the interpolation format syntax, which seemed a bit convoluted and difficult to parse:</span><br class=""></blockquote><blockquote type="cite" class=""><blockquote type="cite" class=""><span class="">"Something with leading zeroes: \(x.format(fill: zero, width:8))"</span><br class=""></blockquote></blockquote><blockquote type="cite" class=""><span class=""></span><br class=""></blockquote><blockquote type="cite" class=""><span class=""></span><br class=""></blockquote><blockquote type="cite" class=""><span class="">Have you considered treating the interpolation parenthesis more like the function call syntax? It should be a familiar pattern and easily parseable to someone versed in other areas of swift:</span><br class=""></blockquote><blockquote type="cite" class=""><span class=""></span><br class=""></blockquote><blockquote type="cite" class=""><span class=""> “Something with leading zeroes: \(x, fill: .zero, width: 8)"</span><br class=""></blockquote><span class=""></span><br class=""><span class="">Yes, we've considered it</span></div><div class=""><br class=""></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""> 1. "\(f(expr1, label2: expr2, label3: expr3))" <br class=""><br class=""> String(describing: f(expr1, label2: expr2, label3: expr3))<br class=""><br class=""> 2. "\(expr0 + expr1(label2: expr2, label3: expr3))"<br class=""><br class=""> String(describing: expr0 + expr1(label2: expr2, label3: expr3)<br class=""><br class=""> 3. "\((expr1, label2: expr2, label3: expr3))"<br class=""><br class=""> String(describing: (expr1, label2: expr2, label3: expr3))<br class=""><br class=""> 4. "\(expr1, label2: expr2, label3: expr3)"<br class=""><br class=""> String(describing: expr1, label2: expr2, label3: expr3)<br class=""><br class="">I think I'm primarily concerned with the differences among cases 1, 3,<br class="">and 4, which are extremely minor. 3 and 4 differ by just a set of<br class="">parentheses, though that might be mitigated by the ${...} suggestion someone else posted. The point of using string interpolation is to improve<br class="">readability, and I fear these cases make too many things look alike that<br class="">have very different meanings. Using a common term like "format" calls<br class="">out what is being done.<br class=""></span></div></div></div></blockquote><div><br class=""></div><div>We should look at this part of the problem as part of reconsidering the way string interpolation works as a whole; there are other problems with our current model, such as not being able to distinguish literal and non-literal segments. I fear that even this:</div><br class=""><blockquote type="cite" class=""><div class=""><div dir="auto" class=""><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">It's possible to produce terser versions of the syntax that don't suffer<br class="">from this problem by using a dedicated operator:<br class=""><br class=""> "Column 1: \(n⛄(radix:16, width:8)) *** \(message)"<br class=""> "Something with leading zeroes: \(x⛄(fill: zero, width:8))"<br class=""></span></div></div></div></blockquote></div><br class=""><div class="">has too many nested delimiters to be easily readable. If we had a string interpolation protocol something like this:</div><div class=""><br class=""></div><div class="">protocol ExpressibleByStringInterpolation {<br class=""> associatedtype LiteralSegment: ExpressibleByStringLiteral<br class=""> associatedtype InterpolatedSegment<br class=""> init()<br class=""><br class=""> mutating func append(literalSegment: LiteralSegment)<br class=""> mutating func append(interpolatedSegment: InterpolatedSegment)<br class="">}<br class=""><br class=""></div><div class="">and "now you have \(n, radix: 16, width: 2) problems" in 'Thingy' context desugared so that \() became a constructor call on the InterpolatedSegment type:</div><div class=""><br class=""></div><div class="">{</div><div class=""> var x = Thingy()</div><div class=""> x.append(literalSegment: "now you have ")</div><div class=""> x.append(interpolatedSegment: Thingy.InterpolatedSegment(n, radix: 16, width: 2))</div><div class=""> x.append(literalSegment: " problems")</div><div class=""> return x</div><div class="">}()</div><div class=""><br class=""></div><div class="">then String.InterpolatedSegment could be a struct that offers interesting formatting initializers.</div><div class=""><br class=""></div><div class="">-Joe</div></body></html>