(Top-replying because Google Inbox.)<br><br>You mentioned a syntax like `let a = ascii(&quot;X&quot;)`. You also mentioned this idea of a facade or currency type. Was any consideration given to making String an enum?<br><br>Freehanding on a phone (not even close to being valid Swift, but hopefully conveys the gist of what I&#39;m saying):<br><br>```<br>enum String {<br>  typealias Index = &lt;whatever we decide on code unit indices&gt;<br>  case ascii(ASCIIString)<br>  case utf8(UTF8String)<br>  case utf16(UTF16String)<br>  //...<br>  case slice(Substring)<br>}<br><br>extension String {<br>  subscript(_ r: Range&lt;Index&gt;) -&gt; String {<br>    return .slice(Substring(_storage: self._storage, _range: r))<br>  }<br>}<br><br>extension ASCIIString : StringProtocol, Unicode { ... }<br>// etc.<br>extension String : StringProtocol, Unicode {<br>// forward to underlying type where appropriate<br>}<br>```<br><br><br><br><div class="gmail_quote"><div dir="ltr">On Sat, Jan 21, 2017 at 14:38 Dave Abrahams via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="auto" class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"><br class="gmail_msg">Sent from my iPad</div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg">On Jan 21, 2017, at 3:49 AM, Brent Royal-Gordon &lt;<a href="mailto:brent@architechies.com" class="gmail_msg" target="_blank">brent@architechies.com</a>&gt; wrote:<br class="gmail_msg"><br class="gmail_msg"></div><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">On Jan 19, 2017, at 6:56 PM, Ben Cohen via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="gmail_msg" target="_blank">swift-evolution@swift.org</a>&gt; wrote:</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">Below is our take on a design manifesto for Strings in Swift 4 and beyond.</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">Probably best read in rendered markdown on GitHub:</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"><a href="https://github.com/apple/swift/blob/master/docs/StringManifesto.md" class="gmail_msg" target="_blank">https://github.com/apple/swift/blob/master/docs/StringManifesto.md</a></span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">We’re eager to hear everyone’s thoughts.</span><br class="gmail_msg"></blockquote><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">There is so, so much good stuff here. </span></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div></div><div dir="auto" class="gmail_msg">Right back atcha, Brent!  Thanks for the detailed review!<div class="gmail_msg"></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><span class="gmail_msg">I&#39;m really looking forward to seeing how these ideas develop and enter the language.</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">#### Future Directions</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">One of the most common internationalization errors is the unintentional</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">presentation to users of text that has not been localized, but regularizing APIs</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">and improving documentation can go only so far in preventing this error.</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">Combined with the fact that `String` operations are non-localized by default,</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">the environment for processing human-readable text may still be somewhat</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">error-prone in Swift 4.</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">For an audience of mostly non-experts, it is especially important that naïve</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">code is very likely to be correct if it compiles, and that more sophisticated</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">issues can be revealed progressively.  For this reason, we intend to</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">specifically and separately target localization and internationalization</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">problems in the Swift 5 timeframe.</span><br class="gmail_msg"></blockquote><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">I am very glad to see this statement in a Swift design document. I have a few ideas about this, but they can wait until the next version.</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">At first blush this just adds work, but consider what it does</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">for equality: two strings that normalize the same, naturally, will collate the</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">same.  But also, *strings that normalize differently will always collate</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">differently*.  In other words, for equality, it is sufficient to compare the</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">strings&#39; normalized forms and see if they are the same.  We can therefore</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">entirely skip the expensive part of collation for equality comparison.</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">Next, naturally, anything that applies to equality also applies to hashing: it</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">is sufficient to hash the string&#39;s normalized form, bypassing collation keys.</span><br class="gmail_msg"></blockquote><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">That&#39;s a great catch.</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">This leaves us executing the full UCA *only* for localized sorting, and ICU&#39;s</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">implementation has apparently been very well optimized.</span><br class="gmail_msg"></blockquote><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">Sounds good to me.</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">Because the current `Comparable` protocol expresses all comparisons with binary</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">operators, string comparisons—which may require</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">additional [options](#operations-with-options)—do not fit smoothly into the</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">existing syntax.  At the same time, we&#39;d like to solve other problems with</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">comparison, as outlined</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">in</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">[this proposal](<a href="https://gist.github.com/CodaFi/f0347bd37f1c407bf7ea0c429ead380e" class="gmail_msg" target="_blank">https://gist.github.com/CodaFi/f0347bd37f1c407bf7ea0c429ead380e</a>)</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">(implemented by changes at the head</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">of</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">[this branch](<a href="https://github.com/CodaFi/swift/commits/space-the-final-frontier" class="gmail_msg" target="_blank">https://github.com/CodaFi/swift/commits/space-the-final-frontier</a>)).</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">We should adopt a modification of that proposal that uses a method rather than</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">an operator `&lt;=&gt;`:</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">```swift</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">enum SortOrder { case before, same, after }</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">protocol Comparable : Equatable {</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">func compared(to: Self) -&gt; SortOrder</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">...</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">}</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">```</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">This change will give us a syntactic platform on which to implement methods with</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">additional, defaulted arguments, thereby unifying and regularizing comparison</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">across the library.</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">```swift</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">extension String {</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">func compared(to: Self) -&gt; SortOrder</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">}</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">```</span><br class="gmail_msg"></blockquote><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">While it&#39;s great that `compared(to:case:etc.)` is parallel to `compared(to:)`, you don&#39;t actually want to *use* anything like `compared(to:)` if you can help it. Think about the clarity at the use site:</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">    if foo.compared(to: bar, case: .insensitive, locale: .current) == .before { … }</span><br class="gmail_msg"></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg">Right.  We intend to keep the usual comparison operators.</div><div class="gmail_msg"><br class="gmail_msg"></div>Poor readability of &quot;foo &lt;=&gt; bar == .before&quot; is another reason we think that giving up on &quot;&lt;=&gt;&quot; is no great loss.<div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg"><div class="gmail_msg"></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><span class="gmail_msg"></span><span class="gmail_msg">The operands and sense of the comparison are kind of lost in all this garbage. You really want to see `foo &lt; bar` in this code somewhere, but you don&#39;t.</span><br class="gmail_msg"></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg">Yeah, we thought about trying to build a DSL for that, but failed.  I think the best possible option would be something like:</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">  foo.comparison(case: .insensitive, locale: .current) &lt; bar</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">The biggest problem is that you can build things like</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">  <span style="background-color:rgba(255,255,255,0)" class="gmail_msg">  fu = foo.comparison(case: .insensitive, locale: .current)</span></div><div class="gmail_msg"><span style="background-color:rgba(255,255,255,0)" class="gmail_msg">    br = bar.comparison(case: .sensitive)</span></div><div class="gmail_msg">    fu &lt; br // what does this mean?</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">We could even prevent such nonsense from compiling, but the cost in library API surface area is quite large.</div><div class="gmail_msg"></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><span class="gmail_msg"></span><span class="gmail_msg">I&#39;m struggling a little with the naming and syntax, but as a general approach, I think we want people to use something more like this:</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">    if StringOptions(case: .insensitive, locale: .current).compare(foo &lt; bar) { … }</span><br class="gmail_msg"></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg">Yeah, we can&#39;t do that without making </div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg"><span class="m_-3089026851060882577Apple-tab-span gmail_msg" style="white-space:pre-wrap">        </span>let a = foo &lt; bar</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">ambiguous</div><div class="gmail_msg"></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><span class="gmail_msg">Which might have an implementation like:</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">    // This protocol might actually be part of your `Unicode` protocol; I&#39;m just breaking it out separately here.</span><br class="gmail_msg"><span class="gmail_msg">    protocol StringOptionsComparable {</span><br class="gmail_msg"><span class="gmail_msg">        func compare(to: Self, options: StringOptions) -&gt; SortOrder</span><br class="gmail_msg"><span class="gmail_msg">    }</span><br class="gmail_msg"><span class="gmail_msg">    extension StringOptionsComparable {</span><br class="gmail_msg"><span class="gmail_msg">        static func &lt; (lhs: Self, rhs: Self) -&gt; (lhs: Self, rhs: Self, op: (SortOrder) -&gt; Bool) {</span><br class="gmail_msg"><span class="gmail_msg">            return (lhs, rhs, { $0 == .before })</span><br class="gmail_msg"><span class="gmail_msg">        }</span><br class="gmail_msg"><span class="gmail_msg">        static func == (lhs: Self, rhs: Self) -&gt; (lhs: Self, rhs: Self, op: (SortOrder) -&gt; Bool) {</span><br class="gmail_msg"><span class="gmail_msg">            return (lhs, rhs, { $0 == .same })</span><br class="gmail_msg"><span class="gmail_msg">        }</span><br class="gmail_msg"><span class="gmail_msg">        static func &gt; (lhs: Self, rhs: Self) -&gt; (lhs: Self, rhs: Self, op: (SortOrder) -&gt; Bool) {</span><br class="gmail_msg"><span class="gmail_msg">            return (lhs, rhs, { $0 == .after })</span><br class="gmail_msg"><span class="gmail_msg">        }</span><br class="gmail_msg"><span class="gmail_msg">        // etc.</span><br class="gmail_msg"><span class="gmail_msg">    }</span><br class="gmail_msg"><span class="gmail_msg">    </span><br class="gmail_msg"><span class="gmail_msg">    struct StringOptions {</span><br class="gmail_msg"><span class="gmail_msg">        // Obvious properties and initializers go here</span><br class="gmail_msg"><span class="gmail_msg">        </span><br class="gmail_msg"><span class="gmail_msg">        func compare&lt;StringType: StringOptionsComparable&gt;(_ expression: (lhs: StringType, rhs: StringType, op: (SortOrder) -&gt; Bool)) -&gt; Bool {</span><br class="gmail_msg"><span class="gmail_msg">            return expression.op( expression.lhs.compare(to: expression.rhs, options: self) )</span><br class="gmail_msg"><span class="gmail_msg">        }</span><br class="gmail_msg"><span class="gmail_msg">    }</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">You could also imagine much less verbose syntaxes using custom operators. Strawman example:</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">    if foo &lt; bar %% (case: .insensitive, locale: .current) { … }</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">I think this would make human-friendly comparisons much easier to write and understand than adding a bunch of options to a `compared(to:)` call.</span><br class="gmail_msg"></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg">That one has the same problem with ambiguity of &quot;a &lt; b&quot;.  There might be an answer here but it&#39;s not obvious and I feel solving it can wait a little.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg"></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">This quirk aside, every aspect of strings-as-collections-of-graphemes appears to</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">comport perfectly with Unicode. We think the concatenation problem is tolerable,</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">because the cases where it occurs all represent partially-formed constructs. </span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">...</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">Admitting these cases encourages exploration of grapheme composition and is</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">consistent with what appears to be an overall Unicode philosophy that “no</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">special provisions are made to get marginally better behavior for… cases that</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">never occur in practice.”[2]</span><br class="gmail_msg"></blockquote><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">This sounds good to me.</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">### Unification of Slicing Operations</span><br class="gmail_msg"></blockquote><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">I think you know what I think about this. :^)</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">(By the way, I&#39;ve at least partially let this proposal drop for the moment because it&#39;s so dependent on generic subscripts to really be an improvement. I do plan to pick it up when those arrive; ping me then if I don&#39;t notice.)</span><br class="gmail_msg"></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg">Okeydoke.</div><div class="gmail_msg"></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><span class="gmail_msg">A question, though. We currently have a couple of methods, mostly with `subrange` in their names, that can be thought of as slicing operations but aren&#39;t:</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">    collection.removeSubrange(i..&lt;j)</span><br class="gmail_msg"><span class="gmail_msg">    collection[i..&lt;j].removeAll()</span><br class="gmail_msg"><span class="gmail_msg">    </span><br class="gmail_msg"><span class="gmail_msg">    collection.replaceSubrange(i..&lt;j, with: others)</span><br class="gmail_msg"><span class="gmail_msg">    collection[i..&lt;j].replaceAll(with: others)        // hypothetically</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">Should these be changed, too? Can we make them efficient (in terms of e.g. copy-on-write) if we do?</span><br class="gmail_msg"></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg">We could, once the ownership model is implemented.  However, I&#39;m not sure whether it&#39;s enough of an improvement to be worth doing.  You could go all the way to</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg"><span class="m_-3089026851060882577Apple-tab-span gmail_msg" style="white-space:pre-wrap">        </span>collection[i..&lt;j] = EmptyCollection()</div><div class="gmail_msg"><span class="m_-3089026851060882577Apple-tab-span gmail_msg" style="white-space:pre-wrap">        </span>collection[i..&lt;j] = others</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">But for that we&#39;d need to (at least) introduce write-only subscripts.</div></div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg"></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">### Substrings</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">When implementing substring slicing, languages are faced with three options:</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">1. Make the substrings the same type as string, and share storage.</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">2. Make the substrings the same type as string, and copy storage when making the substring.</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">3. Make substrings a different type, with a storage copy on conversion to string.</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">We think number 3 is the best choice.</span><br class="gmail_msg"></blockquote><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">I agree, and I think `Substring` is the right name for it: parallel to `SubSequence`, explains where it comes from, captures the trade-offs nicely. `StringSlice` is parallel to `ArraySlice`, but it strikes me as a &quot;foolish consistency&quot;, as the saying goes; it avoids a term of art for little reason I can see.</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">However, is there a reason we&#39;re talking about using a separate `Substring` type at all, instead of using `Slice&lt;String&gt;`? </span></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg">Yes: we couldn&#39;t specialize its representation to store short substrings inline, at least not without introducing an undesirable level of complexity.</div><div class="gmail_msg"></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"> <br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><span class="gmail_msg">Perhaps I&#39;m missing something, but I *think* it does everything we need here. (Of course, you could say the same thing about `ArraySlice`, and yet we have that, too.)</span><br class="gmail_msg"></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg">ArraySlice is doomed :-)</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg"><a href="https://bugs.swift.org/browse/SR-3631" class="gmail_msg" target="_blank">https://bugs.swift.org/browse/SR-3631</a></div><div class="gmail_msg"></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">The downside of having two types is the inconvenience of sometimes having a</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">`Substring` when you need a `String`, and vice-versa. It is likely this would</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">be a significantly bigger problem than with `Array` and `ArraySlice`, as</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">slicing of `String` is such a common operation. It is especially relevant to</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">existing code that assumes `String` is the currency type. To ease the pain of</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">type mismatches, `Substring` should be a subtype of `String` in the same way</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">that `Int` is a subtype of `Optional&lt;Int&gt;`.</span><br class="gmail_msg"></blockquote><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">I&#39;ve seen people struggle with the `Array`/`ArraySlice` issue when writing recursive algorithms, so personally, I&#39;d like to see a more general solution that handles all `Collection`s.</span><br class="gmail_msg"></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg">The more general solution is &quot;extend Unicode&quot; or &quot;extend Collection&quot; (and when a String <u class="gmail_msg">parameter</u> is needed, &quot;make your method generic over Collection/Unicode&quot;).</div><div class="gmail_msg"></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><span class="gmail_msg">Rather than having an implicit copying conversion from `String` to `Substring` (or `Array` to `ArraySlice`, or `Collection` to `Collection.SubSequence`), I wonder if implicitly converting in the other direction might be more useful, at least in some circumstances. Converting in this direction does *not* involve an implicit copy, merely calculating a range, so you won&#39;t have the same performance surprises. On the other hand, it&#39;s also useful in fewer situations.</span><br class="gmail_msg"></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg">That&#39;s the problem, right there, combined with the fact that we don&#39;t have a terse syntax like s[] for going the other way.  I think it would be a much more elegant design, personally, but I don&#39;t see the tradeoffs working out.  If we can come up with a way to do it that works, we should.  So far, Ben and I have failed.</div><div class="gmail_msg"></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><span class="gmail_msg"></span><span class="gmail_msg">(If we did go with consistently using `Slice&lt;T&gt;`, this might merely be a special-cased `T -&gt; Slice&lt;T&gt;` conversion. One type, special-cased until we feel comfortable inventing a general mechanism.)</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">A user who needs to optimize away copies altogether should use this guideline:</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">if for performance reasons you are tempted to add a `Range` argument to your</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">method as well as a `String` to avoid unnecessary copies, you should instead</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">use `Substring`.</span><br class="gmail_msg"></blockquote><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">I do like this as a guideline, though. There&#39;s definitely room in the standard library for &quot;a string and a range of that string to operate upon&quot;.</span><br class="gmail_msg"></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg">I don&#39;t know what you mean.  It&#39;s our intention that nothing but the lowest level operations (e.g. replaceRange) would work on ranges when they could instead be working on slices.</div><div class="gmail_msg"><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"></div></blockquote></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">##### The “Empty Subscript”</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">To make it easy to call such an optimized API when you only have a `String` (or</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">to call any API that takes a `Collection`&#39;s `SubSequence` when all you have is</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">the `Collection`), we propose the following “empty subscript” operation,</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"></blockquote></div></blockquote></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">I```swift</span><br class="gmail_msg"></blockquote></div></blockquote></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">extension Collection {</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"> subscript() -&gt; SubSequence { </span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">   return self[startIndex..&lt;endIndex] </span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"> }</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">}</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">```</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">which allows the following usage:</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">```swift</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">funcThatIsJustLooking(at: <a href="http://person.name" class="gmail_msg" target="_blank">person.name</a>[]) // pass <a href="http://person.name" class="gmail_msg" target="_blank">person.name</a> as Substring</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">```</span><br class="gmail_msg"></blockquote><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">That&#39;s a little bit funky, but I guess it might work.</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">Therefore, APIs that operate on an `NSString`/`NSRange` pair should be imported</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">without the `NSRange` argument.  The Objective-C importer should be changed to</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">give these APIs special treatment so that when a `Substring` is passed, instead</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">of being converted to a `String`, the full `NSString` and range are passed to</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">the Objective-C method, thereby avoiding a copy.</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">As a result, you would never need to pass an `NSRange` to these APIs, which</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">solves the impedance problem by eliminating the argument, resulting in more</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">idiomatic Swift code while retaining the performance benefit.  To help users</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">manually handle any cases that remain, Foundation should be augmented to allow</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">the following syntax for converting to and from `NSRange`:</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">```swift</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">let nsr = NSRange(i..&lt;j, in: s) // An NSRange corresponding to s[i..&lt;j]</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">let iToJ = Range(nsr, in: s)    // Equivalent to i..&lt;j</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">```</span><br class="gmail_msg"></blockquote><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">I sort of like this, but note that if we use `String` -&gt; `Substring` conversion instead of the other way around, there&#39;s less magic needed to get this effect: `NSString, NSRange` can be imported as `Substring`, which automatically converts from `String` in exactly the manner we want it to.</span><br class="gmail_msg"></div></blockquote></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div>Indeed.</div><div class="gmail_msg"></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">Since Unicode conformance is a key feature of string processing in swift, we</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">call that protocol `Unicode`:</span><br class="gmail_msg"></blockquote><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">I&#39;m sorry, I think the name is too clever by half. It sounds something like what `UnicodeCodec` actually is. Or maybe a type representing a version of the Unicode standard or something. I&#39;d prefer something more prosaic like `StringProtocol`.</span><br class="gmail_msg"></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg">It&#39;s an option we considered.  So far I think Unicode is better (most especially if we end up with a &quot;facade&quot; design) but we should discuss it.</div><div class="gmail_msg"></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"> <br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">**Note:** `Unicode` would make a fantastic namespace for much of</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">what&#39;s in this proposal if we could get the ability to nest types and</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">protocols in protocols.</span><br class="gmail_msg"></blockquote><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">I mean, sure, but then you imagine it being used generically:</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">    func parse&lt;UnicodeType: Unicode&gt;(_ source: UnicodeType) -&gt; UnicodeType</span><br class="gmail_msg"><span class="gmail_msg">    // which concrete types can `source` be???</span><br class="gmail_msg"></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg">All &quot;string&quot; types, including String, Substring, UTF8String, StaticString, etc.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg"></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">We should provide convenient APIs processing strings by character.  For example,</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">it should be easy to cleanly express, “if this string starts with `&quot;f&quot;`, process</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">the rest of the string as follows…”  Swift is well-suited to expressing this</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">common pattern beautifully, but we need to add the APIs.  Here are two examples</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">of the sort of code that might be possible given such APIs:</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">```swift</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">if let firstLetter = input.droppingPrefix(alphabeticCharacter) {</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"> somethingWith(input) // process the rest of input</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">}</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">if let (number, restOfInput) = input.parsingPrefix(Int.self) {</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">  ...</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">}</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">```</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">The specific spelling and functionality of APIs like this are TBD.  The larger</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">point is to make sure matching-and-consuming jobs are well-supported.</span><br class="gmail_msg"></blockquote><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">Yes.</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">#### Unified Pattern Matcher Protocol</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">Many of the current methods that do matching are overloaded to do the same</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">logical operations in different ways, with the following axes:</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">- Logical Operation: `find`, `split`, `replace`, match at start</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">- Kind of pattern: `CharacterSet`, `String`, a regex, a closure</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">- Options, e.g. case/diacritic sensitivity, locale.  Sometimes a part of</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"> the method name, and sometimes an argument</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">- Whole string or subrange.</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">We should represent these aspects as orthogonal, composable components,</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">abstracting pattern matchers into a protocol like</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">[this one](<a href="https://github.com/apple/swift/blob/master/test/Prototypes/PatternMatching.swift#L33" class="gmail_msg" target="_blank">https://github.com/apple/swift/blob/master/test/Prototypes/PatternMatching.swift#L33</a>),</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">that can allow us to define logical operations once, without introducing</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">overloads, and massively reducing API surface area.</span><br class="gmail_msg"></blockquote><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">*Very* yes.</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">For example, using the strawman prefix `%` syntax to turn string literals into</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">patterns, the following pairs would all invoke the same generic methods:</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">```swift</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">if let found = s.firstMatch(%&quot;searchString&quot;) { ... }</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">if let found = s.firstMatch(someRegex) { ... }</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">for m in s.allMatches((%&quot;searchString&quot;), case: .insensitive) { ... }</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">for m in s.allMatches(someRegex) { ... }</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">let items = s.split(separatedBy: &quot;, &quot;)</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">let tokens = s.split(separatedBy: CharacterSet.whitespace)</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">```</span><br class="gmail_msg"></blockquote><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">Very, *very* yes.</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">If we do this, rather than your `%` operator (or whatever it becomes), I wonder if we can have these extensions:</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">    // Assuming a protocol like:</span><br class="gmail_msg"><span class="gmail_msg">    protocol Pattern {</span><br class="gmail_msg"><span class="gmail_msg">        associatedtype PatternElement</span><br class="gmail_msg"><span class="gmail_msg">        func matches&lt;CollectionType: Collection&gt;(…) -&gt; … where CollectionType.Element == Element</span><br class="gmail_msg"><span class="gmail_msg">    }</span><br class="gmail_msg"><span class="gmail_msg">    extension Equatable: Pattern {</span><br class="gmail_msg"><span class="gmail_msg">        typealias PatternElement = Self</span><br class="gmail_msg"><span class="gmail_msg">        …</span><br class="gmail_msg"><span class="gmail_msg">    }</span><br class="gmail_msg"><span class="gmail_msg">    extension Collection: Pattern where Element: Equatable {</span><br class="gmail_msg"><span class="gmail_msg">        typealias PatternElement = Element</span><br class="gmail_msg"><span class="gmail_msg">    }</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">...although then `Collection` would conform to `Pattern` through both itself and (conditionally) `Equatable`. Hmm.</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">I suppose we faced this same problem elsewhere and ended up with things like:</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">    mutating func append(_ element: Element)</span><br class="gmail_msg"><span class="gmail_msg">    mutating func append&lt;Seq: Sequence&gt;(contentsOf seq: Seq) where Seq.Iterator.Element == Element</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">So we could do things like:</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">    str.firstMatch(&quot;x&quot;)    // single element, so this is a Character</span><br class="gmail_msg"><span class="gmail_msg">    str.firstMatch(contentsOf(&quot;xy&quot;))</span><br class="gmail_msg"><span class="gmail_msg">    str.firstMatch(anyOf([&quot;x&quot;, &quot;y&quot;] as Set))</span><br class="gmail_msg"></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg">I really, really want to explore these ideas further, and I really, really don&#39;t want to do it in this thread, if you don&#39;t mind.  There are lots of ways to slice this particular cupcake.</div><div class="gmail_msg"></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">#### Index Interchange Among Views</span><br class="gmail_msg"></blockquote><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">I really, really, really want this.</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">We think random-access</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">*code-unit storage* is a reasonable requirement to impose on all `String`</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">instances.</span><br class="gmail_msg"></blockquote><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">Wait, you do? Doesn&#39;t that mean either using UTF-32, inventing a UTF-24 to use, or using some kind of complicated side table that adjusts for all the multi-unit characters in a UTF-16 or UTF-8 string? None of these sound ideal.</span><br class="gmail_msg"></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg">No; I&#39;m not sure why you would think that.</div><div class="gmail_msg"></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><span class="gmail_msg"></span><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">Index interchange between `String` and its `unicodeScalars`, `codeUnits`,</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">and [`extendedASCII`](#parsing-ascii-structure) views can be made entirely</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">seamless by having them share an index type (semantics of indexing a `String`</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">between grapheme cluster boundaries are TBD—it can either trap or be forgiving).</span><br class="gmail_msg"></blockquote><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">I think it should be forgiving, and I think it should be forgiving in a very specific way: It should treat indexing in the middle of a cluster as though you indexed at the beginning.</span><br class="gmail_msg"></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg">That&#39;s my intuition as well.</div><div class="gmail_msg"></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><span class="gmail_msg"></span><span class="gmail_msg">The reason is `AttributedString`. You can think of `AttributedString` as being a type which adds additional views to a `String`; these views are indexed by `String.Index`, just like `String`, `String.UnicodeScalarView`, <a href="http://et.al" class="gmail_msg" target="_blank">et.al</a>., and advancing an index with these views advances it to the beginning of the next run. But you can also just subscript these views with an arbitrary index in the middle of a run, and it&#39;ll work correctly.</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">I think it would be useful for this behavior to be consistent among all `String` views.</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">Having a common index allows easy traversal into the interior of graphemes,</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">something that is often needed, without making it likely that someone will do it</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">by accident.</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">- `String.index(after:)` should advance to the next grapheme, even when the</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">  index points partway through a grapheme.</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">- `String.index(before:)` should move to the start of the grapheme before</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">  the current position.</span><br class="gmail_msg"></blockquote><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">Good.</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">Seamless index interchange between `String` and its UTF-8 or UTF-16 views is not</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">crucial, as the specifics of encoding should not be a concern for most use</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">cases, and would impose needless costs on the indices of other views.</span><br class="gmail_msg"></blockquote><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">I don&#39;t know about this, at least for the UTF-16 view. Here&#39;s why:</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">That leaves the interchange of bare indices with Cocoa APIs trafficking in</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">`Int`.  Hopefully such APIs will be rare, but when needed, the following</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">extension, which would be useful for all `Collections`, can help:</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">```swift</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">extension Collection {</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"> func index(offset: IndexDistance) -&gt; Index {</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">   return index(startIndex, offsetBy: offset)</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"> }</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"> func offset(of i: Index) -&gt; IndexDistance {</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">   return distance(from: startIndex, to: i)</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"> }</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">}</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">```</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">Then integers can easily be translated into offsets into a `String`&#39;s `utf16`</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">view for consumption by Cocoa:</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">```swift</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">let cocoaIndex = s.utf16.offset(of: String.UTF16Index(i))</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">let swiftIndex = s.utf16.index(offset: cocoaIndex)</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">```</span><br class="gmail_msg"></blockquote><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">I worry that this conversion will be too obscure.</span></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg">I very much hope it will be rare enough that it&#39;ll be OK, but if it isn&#39;t, we can always have</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg"><span class="m_-3089026851060882577Apple-tab-span gmail_msg" style="white-space:pre-wrap">        </span>l<span style="background-color:rgba(255,255,255,0)" class="gmail_msg">et cocoaIndex = s.utf16Offset(of: i)</span></div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">and/or take other measures to simplify it.</div><div class="gmail_msg"></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><span class="gmail_msg">In Objective-C, you don&#39;t really think very much about what &quot;character&quot; means; it&#39;s just an index that points to a location inside the string. I don&#39;t think people will know to use the `utf16` view instead of the others—especially the plain `String` version, which would be the most obvious one to use.</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">I think I&#39;d prefer to see the following:</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">1. UTF-16 is the storage format, at least for an &quot;ordinary&quot; `Swift.String`.</span><br class="gmail_msg"></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg">It will be, in the common case, but <u class="gmail_msg">many</u> people seem to want plain String to be able to store UTF-8, and I&#39;m not yet prepared to rule that out.</div><div class="gmail_msg"></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><span class="gmail_msg"></span><span class="gmail_msg">2. `String.Index` is used down to the `UTF16View`. It stores a UTF-16 offset.</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">3. With just the standard library imported, `String.Index` does not have any obvious way to convert to or from an `Int` offset; you use `index(_:offsetBy:)` on one of the views. `utf16`&#39;s implementation is just faster than the others.</span><br class="gmail_msg"></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg">This is roughly where we are today.</div><div class="gmail_msg"><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"></div></blockquote></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><span class="gmail_msg">4. Foundation adds `init(_:)` methods to `String.Index` and `Int`, as well as `Range&lt;String.Index&gt;` and `NSRange`, which perform mutual conversions:</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">    XCTAssertEqual(Int(String.Index(cocoaIndex)), cocoaIndex)</span><br class="gmail_msg"><span class="gmail_msg">    XCTAssertEqual(NSRange(Range&lt;String.Index&gt;(cocoaRange)), cocoaRange)</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">I think this would really help to guide people to the right APIs for the task.</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">(Also, it would make my `AttributedString` thing work better, too.)</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">### Formatting</span><br class="gmail_msg"></blockquote><span class="gmail_msg"></span><br class="gmail_msg"></div></blockquote></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><span class="gmail_msg">Briefly: I am, let&#39;s say, 95% on board with your plan to replace format strings with interpolation and format methods. The remaining 5% concern is that it we&#39;ll need an adequate replacement for the ability to load a format string dynamically and have it reorder or alter the formatting of interpolated values. Obviously dynamic format strings are dangerous and limited, but where you *can* use them, they&#39;re invaluable.\</span><br class="gmail_msg"></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div>Yes.  We have ideas, though they&#39;re far from baked.</div><div class="gmail_msg"></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">#### String Interpolation</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">Swift string interpolation provides a user-friendly alternative to printf&#39;s</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">domain-specific language (just write ordinary swift code!) and its type safety</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">problems (put the data right where it belongs!) but the following issues prevent</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">it from being useful for localized formatting (among other jobs):</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"> * [SR-2303](<a href="https://bugs.swift.org/browse/SR-2303" class="gmail_msg" target="_blank">https://bugs.swift.org/browse/SR-2303</a>) We are unable to restrict</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">   types used in string interpolation.</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"> * [SR-1260](<a href="https://bugs.swift.org/browse/SR-1260" class="gmail_msg" target="_blank">https://bugs.swift.org/browse/SR-1260</a>) String interpolation can&#39;t</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">   distinguish (fragments of) the base string from the string substitutions.</span><br class="gmail_msg"></blockquote><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">If I find some copious free time, I could try to develop proposals for one or both of these. Would there be interest in them at this point? (Feel free to contact me off-list about this, preferably in a new thread.)</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">(Okay, one random thought, because I can&#39;t resist: Perhaps the &quot;\(…)&quot; syntax can be translated directly into an `init(…)` on the type you&#39;re creating. That is, you can write:</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">    let x: MyString = &quot;foo \(bar) baz \(quux, radix: 16)&quot;</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">And that translates to:</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">    let x = MyString(stringInterpolationSegments:</span><br class="gmail_msg"><span class="gmail_msg">        MyString(stringLiteral: &quot;foo &quot;),</span><br class="gmail_msg"><span class="gmail_msg">        MyString(bar),</span><br class="gmail_msg"><span class="gmail_msg">        MyString(stringLiteral: &quot; baz &quot;),</span><br class="gmail_msg"><span class="gmail_msg">        MyString(quux, radix: 16)</span><br class="gmail_msg"><span class="gmail_msg">    )</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">That would require you to redeclare `String` initializers on your own string type, but you probably need some of your own logic anyway, right?)</span><br class="gmail_msg"></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg">Let&#39;s go to a separate thread for this, as you suggested.</div><div class="gmail_msg"></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">In the long run, we should improve Swift string interpolation to the point where</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">it can participate in most any formatting job.  Mostly this centers around</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">fixing the interpolation protocols per the previous item, and supporting</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">localization.</span><br class="gmail_msg"></blockquote><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">For what it&#39;s worth, by using a hacky workaround for SR-1260, I&#39;ve written (Swift 2.0) code that passes strings with interpolations through the Foundation localized string tables: &lt;<a href="https://gist.github.com/brentdax/79fa038c0af0cafb52dd" class="gmail_msg" target="_blank">https://gist.github.com/brentdax/79fa038c0af0cafb52dd</a>&gt; Obviously that&#39;s just a start, but it is incredibly convenient.</span><br class="gmail_msg"></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg">I know; it&#39;s an inspiration :-)</div><div class="gmail_msg"></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">### C String Interop</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">Our support for interoperation with nul-terminated C strings is scattered and</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">incoherent, with 6 ways to transform a C string into a `String` and four ways to</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">do the inverse.  These APIs should be replaced with the following</span><br class="gmail_msg"></blockquote><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">These APIs are much better than the status quo, but it&#39;s a shame that we can&#39;t have them handle non-nul-terminated data, too.</span><br class="gmail_msg"></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg">We thought about unifying them with other transcoding APIs, but the pointer-to-nul-terminated-code-units case is sufficiently important that we think they deserve dedicated support.</div><div class="gmail_msg"></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><span class="gmail_msg"></span><span class="gmail_msg">Actually... (Begin shaggy dog story...)</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">Suppose you introduce an `UnsafeNulTerminatedBufferPointer` type. Then you could write a *very* high-level API which handles pretty much every conversion under the sun:</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">    extension String {</span><br class="gmail_msg"><span class="gmail_msg">        /// Constructs a `String` from a sequence of `codeUnits` in an indicated `encoding`.</span><br class="gmail_msg"><span class="gmail_msg">        /// </span><br class="gmail_msg"><span class="gmail_msg">        /// - Parameter codeUnits: A sequence of code units in the given `encoding`.</span><br class="gmail_msg"><span class="gmail_msg">        /// - Parameter encoding: The encoding the code units are in.</span><br class="gmail_msg"><span class="gmail_msg">        init&lt;CodeUnits: Sequence, Encoding: UnicodeEncoding&gt;(_ codeUnits: CodeUnits, encoding: Encoding)</span><br class="gmail_msg"><span class="gmail_msg">            where CodeUnits.Iterator.Element == Encoding.CodeUnit</span><br class="gmail_msg"><span class="gmail_msg">    }</span><br class="gmail_msg"></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg">Yes, we intend to support something like that.</div><div class="gmail_msg"></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><span class="gmail_msg">For UTF-8, at least, that would cover reading from `Array`, `UnsafeBufferPointer`, `UnsafeRawBufferPointer`, `UnsafeNulTerminatedBufferPointer`, `Data`, you name it. Maybe we could have a second one that always takes something producing bytes, no matter the encoding used:</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">    extension String {</span><br class="gmail_msg"><span class="gmail_msg">        /// Constructs a `String` from the code units contained in `bytes` in a given `encoding`.</span><br class="gmail_msg"><span class="gmail_msg">        /// </span><br class="gmail_msg"><span class="gmail_msg">        /// - Parameter bytes: A sequence of bytes expressing code units in the given `encoding`.</span><br class="gmail_msg"><span class="gmail_msg">        /// - Parameter encoding: The encoding the code units are in.</span><br class="gmail_msg"><span class="gmail_msg">        init&lt;Bytes: Sequence, Encoding: UnicodeEncoding&gt;(_ codeUnits: CodeUnits, encoding: Encoding)</span><br class="gmail_msg"><span class="gmail_msg">            where CodeUnits.Iterator.Element == UInt8</span><br class="gmail_msg"><span class="gmail_msg">    }</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">These two initializers would replace...um, something like eight existing ones, including ones from Foundation. On the other hand, this is *very* generic. And, unless we actually changed the way `char *` imported to `UnsafeNulTerminatedBufferPointer&lt;CChar&gt;`, the C string call sequence would be pretty complicated:</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">    String(UnsafeNulTerminatedBufferPointer(start: cString), encoding: UTF8.self)</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">So you might end up having to wrap it in an `init(cString:)` anyway, just for convenience. Oh well, it was worth exploring.</span><br class="gmail_msg"></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg">I think you ended up where we did.</div><div class="gmail_msg"></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><span class="gmail_msg">Prototype of the above: <a href="https://gist.github.com/brentdax/8b71f46b424dc64abaa77f18556e607b" class="gmail_msg" target="_blank">https://gist.github.com/brentdax/8b71f46b424dc64abaa77f18556e607b</a></span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">(Hmm...maybe bridge `char *` to a type like this instead?</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">    struct CCharPointer {</span><br class="gmail_msg"><span class="gmail_msg">        var baseAddress: UnsafePointer&lt;CChar&gt; { get }</span><br class="gmail_msg"><span class="gmail_msg">        var nulTerminated: UnsafeNulTerminatedBufferPointer&lt;CChar&gt; { get }</span><br class="gmail_msg"><span class="gmail_msg">        func ofLength(_ length: Int) -&gt; UnsafeBufferPointer&lt;CChar&gt;</span><br class="gmail_msg"><span class="gmail_msg">    }</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">Nah, probably not gonna happen...)</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"> init(cString nulTerminatedUTF8: UnsafePointer&lt;CChar&gt;)</span><br class="gmail_msg"></blockquote><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">By the way, I just noticed an impedance mismatch in current Swift: `CChar` is usually an `Int8`, but `UnicodeScalar` and `UTF8` currently want `UInt8`. It&#39;d be nice to address this somehow, if only by adding some signed variants or something.</span><br class="gmail_msg"></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg">We thought about that problem and landed on the proposed interface above as all that is needed to resolve it.</div><div class="gmail_msg"></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">### High-Performance String Processing</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">Many strings are short enough to store in 64 bits, many can be stored using only</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">8 bits per unicode scalar, others are best encoded in UTF-16, and some come to</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">us already in some other encoding, such as UTF-8, that would be costly to</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">translate.  Supporting these formats while maintaining usability for</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">general-purpose APIs demands that a single `String` type can be backed by many</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">different representations.</span><br class="gmail_msg"></blockquote><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">Just putting a pin in this, because I&#39;ll want to discuss it a little later.</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">### Parsing ASCII Structure</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">Although many machine-readable formats support the inclusion of arbitrary</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">Unicode text, it is also common that their fundamental structure lies entirely</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">within the ASCII subset (JSON, YAML, many XML formats).  These formats are often</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">processed most efficiently by recognizing ASCII structural elements as ASCII,</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">and capturing the arbitrary sections between them in more-general strings.  The</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">current String API offers no way to efficiently recognize ASCII and skip past</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">everything else without the overhead of full decoding into unicode scalars.</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">For these purposes, strings should supply an `extendedASCII` view that is a</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">collection of `UInt32`, where values less than `0x80` represent the</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">corresponding ASCII character, and other values represent data that is specific</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">to the underlying encoding of the string.</span><br class="gmail_msg"></blockquote><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">This sounds interesting, but:</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">1. It doesn&#39;t sound like you anticipate there being any way to compare an element of the `extendedASCII` view to a character literal. That seems like it&#39;d be really useful.</span><br class="gmail_msg"></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg">We don&#39;t have character literals :-)</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">However, I agree that there needs to be a way to do it.  The thing would be to make it easy to construct a UInt8 from a string literal.  There are a few possibilities; <span style="background-color:rgba(255,255,255,0)" class="gmail_msg">I&#39;m a little nervous about making this work:</span></div><div class="gmail_msg"><span style="background-color:rgba(255,255,255,0)" class="gmail_msg"><br class="gmail_msg"></span></div><div class="gmail_msg"><span style="background-color:rgba(255,255,255,0)" class="gmail_msg"><span class="m_-3089026851060882577Apple-tab-span gmail_msg" style="white-space:pre-wrap">        </span>if c == &quot;X&quot; { ... }</span></div><div class="gmail_msg"><span style="background-color:rgba(255,255,255,0)" class="gmail_msg"><br class="gmail_msg"></span></div><div class="gmail_msg">but maybe I should just get over it.  The cleanest alternative I can think of is:</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg"><span class="m_-3089026851060882577Apple-tab-span gmail_msg" style="white-space:pre-wrap">        </span>if c == ascii(&quot;X&quot;) { ... }</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">where &quot;X&quot; is required by the compiler to be a single ascii character.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">I guess another possibility is to introduce an ASCII type and overload operators so it can be compared with all the Ints:</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg"><span class="m_-3089026851060882577Apple-tab-span gmail_msg" style="white-space:pre-wrap">        </span>if c == &quot;X&quot; as ASCII { ... }</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg"></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><span class="gmail_msg">2. I don&#39;t really understand how you envision using the &quot;data specific to the underlying encoding&quot; sections. Presumably you&#39;ll want to convert that data into a string eventually, right?</span><br class="gmail_msg"></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg">It already <u class="gmail_msg">is</u> in a string.  The point is that we have a way to scan the string looking for ASCII patterns without transcoding it.</div><div class="gmail_msg"></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><span class="gmail_msg">Do you have pseudocode or something lying around that might help us understand how you think this might be used?</span><br class="gmail_msg"></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg">Not exactly.  The pattern matching prototype you referred to earlier would be enhanced to use the extendedASCII view when it was available and the pattern being matched was suitably restricted.  How, exactly, that works is still a bit of a research project though.</div><div class="gmail_msg"></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><span class="gmail_msg"></span><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">### Do we need a type-erasable base protocol for UnicodeEncoding?</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">UnicodeEncoding has an associated type, but it may be important to be able to</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">traffic in completely dynamic encoding values, e.g. for “tell me the most</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">efficient encoding for this string.”</span><br class="gmail_msg"></blockquote><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">As long as you&#39;re here, we haven&#39;t talked about `UnicodeEncoding` much. I assume this is a slightly modified version of `UnicodeCodec`? Anything to say about it?</span><br class="gmail_msg"></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg">That&#39;s basically right.  You can see a first cut at it in the unicode-rethink branch on GitHub.</div><div class="gmail_msg"></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><span class="gmail_msg"></span><span class="gmail_msg">If it *is* similar to `UnicodeCodec`, one thing I will note is that the way `UnicodeCodec` works in code units is rather annoying for I/O. It may make sense to have some sort of type-erasing wrapper around `UnicodeCodec` which always uses bytes. (You then have to worry about endianness, of course...)</span><br class="gmail_msg"></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg">Take a look at the branch and let me know how this looks like it would work for I/O.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">By the way, I think I/O really needs a special kind of collection: a sort of deque built out of I/O buffer-sized chunks that are filled on demand from a Sequence.  That is part, at least, of how I justify UnicodeEncoding having a Collection-based interface where UnicodeCodec used Iterator.</div><div class="gmail_msg"></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">### Should there be a string “facade?”</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">…</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">An interesting variation on this design is possible if defaulted generic</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">parameters are introduced to the language:</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">```swift</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">struct String&lt;U: Unicode = StringStorage&gt; </span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"> : BidirectionalCollection {</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"> // ...APIs for high-level string processing here...</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"> var unicode: U // access to lower-level unicode details</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">}</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">typealias Substring = String&lt;StringStorage.SubSequence&gt;</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">```</span><br class="gmail_msg"></blockquote><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">I think this is a very, very interesting idea. A few notes:</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">* Earlier, I said I didn&#39;t like `Unicode` as a protocol name. If we go this route, I think `StringStorage` is a good name for that protocol. The default storage might be something like `UTF16StringStorage`, or just, you know, `DefaultStringStorage`.</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">* Earlier, you mentioned the tension between using multiple representations for flexibility and pinning down one representation for speed. One way to handle this might be to have `String`&#39;s default `StringStorage` be a superclass or type-erased wrapper or something.</span></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div>Yes, that&#39;s the idea.</div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><span class="gmail_msg"> That way, if you just write `String`, you get something flexible; if you write `String&lt;NFCNormalizedUTF16StringStorage&gt;`, you get something fast.</span><br class="gmail_msg"></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg">This only works in the &quot;facade&quot; variant where you have a defaulted generic parameter feature, but yes, that&#39;s the idea of that variant.</div><div class="gmail_msg"></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><span class="gmail_msg"></span><span class="gmail_msg">* Could `NSString` be a `StringStorage`, or support a trivial wrapper that converts it into a `StringStorage`? Would that be helpful at all?</span><br class="gmail_msg"></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg">Yes, that&#39;s part of the idea.</div><div class="gmail_msg"></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><span class="gmail_msg"></span><span class="gmail_msg">* If we do this, does `String.Index` become a type-specific thing? That is, might `String&lt;UTF8Storage&gt;.Index` be different from `String&lt;UTF16Storage&gt;.Index`? </span></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg">Yes.</div><div class="gmail_msg"></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><span class="gmail_msg">What does that mean for `String.Index` unification?</span><br class="gmail_msg"></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg">Not much.  We never intended for indices to be interchangeable among different specific string types (other than a string and its SubSequence).</div><div class="gmail_msg"></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">### `description` and `debugDescription`</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">* Should these be creating localized or non-localized representations?</span><br class="gmail_msg"></blockquote><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">`debugDescription`, I think, is non-localized; it&#39;s something helpful for the programmer, and the programmer&#39;s language is not the user&#39;s. It&#39;s also usually something you don&#39;t want to put *too* much effort into, other than to dump a lot of data about the instance.</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">`description` would have to change to be localizable. (Specifically, it would have to take a locale.) This is doable, of course, but it hasn&#39;t been done yet.</span><br class="gmail_msg"></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg">Well, it could use the current locale.  These things are supposed to remain lightweight.</div><div class="gmail_msg"></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><span class="gmail_msg"></span><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">* Is returning a `String` efficient enough?</span><br class="gmail_msg"></blockquote><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">I&#39;m not sure how important efficiency is for `description`, honestly.</span><br class="gmail_msg"></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg">It depends how intimately this is tied into interpolation and formatting, I think.</div><div class="gmail_msg"></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">* Is `debugDescription` pulling the weight of the API surface area it adds?</span><br class="gmail_msg"></blockquote><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">Maybe? Or maybe it&#39;s better off as part of the `Mirror` instead of a property on the instance itself.</span><br class="gmail_msg"></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg">That&#39;s a very interesting thought!</div><div class="gmail_msg"></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><span class="gmail_msg"></span><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">### `StaticString`</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">`StaticString` was added as a byproduct of standard library developed and kept</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">around because it seemed useful, but it was never truly *designed* for client</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">programmers.  We need to decide what happens with it.  Presumably *something*</span><br class="gmail_msg"></blockquote><blockquote type="cite" class="gmail_msg"><span class="gmail_msg">should fill its role, and that should conform to `Unicode`.</span><br class="gmail_msg"></blockquote><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">Maybe. One complication there is that `Unicode` presumably supports mutation, which `StaticString` doesn&#39;t.</span><br class="gmail_msg"></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg">No, Unicode doesn&#39;t support mutation.  A mutable Unicode will usually conform to Unicode and RangeReplaceableCollection (but not MutableCollection, because replacing a grapheme is not an O(1) operation).</div><div class="gmail_msg"></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><span class="gmail_msg">Another possibility I&#39;ve discussed in the past is renaming `StaticString` to `StringLiteral` and using it largely as a way to initialize `String`. (I mentioned that in a thread about the need for public integer and floating-point literal types that are more expressive now that we&#39;re supporting larger integer/float types.) </span></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg">Yes, a broad redesign of all literals is crucial.  However, there are other sources of static string data than literals and those need to be accommodated.</div><div class="gmail_msg"></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><span class="gmail_msg">It could have just enough API surface to access it as a buffer of UTF-8 bytes and thereby build a `String` or `Data` from it.</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"><span class="gmail_msg">Well, that&#39;s it for this massive email. You guys are doing a hell of a job on this.</span><br class="gmail_msg"></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div></div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg">Thanks for all the feedback, and the encouragement!</div></div></div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><span class="gmail_msg">Hope this helps,</span><br class="gmail_msg"><span class="gmail_msg">-- </span><br class="gmail_msg"><span class="gmail_msg">Brent Royal-Gordon</span><br class="gmail_msg"><span class="gmail_msg">Architechies</span><br class="gmail_msg"><span class="gmail_msg"></span><br class="gmail_msg"></div></blockquote></div></div></div></div>_______________________________________________<br class="gmail_msg">
swift-evolution mailing list<br class="gmail_msg">
<a href="mailto:swift-evolution@swift.org" class="gmail_msg" target="_blank">swift-evolution@swift.org</a><br class="gmail_msg">
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" class="gmail_msg" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class="gmail_msg">
</blockquote></div>