<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">Very nice improvements overall!</div><div class=""><br class=""></div><br class=""><div class=""><blockquote type="cite" class=""><span style="color: rgb(51, 51, 51); font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; background-color: rgb(255, 255, 255);" class="">To ease the pain of type mismatches, </span><code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; color: rgb(51, 51, 51);" class="">Substring</code><span style="color: rgb(51, 51, 51); font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; background-color: rgb(255, 255, 255);" class=""> should be a subtype of </span><code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; color: rgb(51, 51, 51);" class="">String</code><span style="color: rgb(51, 51, 51); font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; background-color: rgb(255, 255, 255);" class=""> in the same way that </span><code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; color: rgb(51, 51, 51);" class="">Int</code><span style="color: rgb(51, 51, 51); font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; background-color: rgb(255, 255, 255);" class=""> is a subtype of </span><code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; color: rgb(51, 51, 51);" class="">Optional<Int></code><span style="color: rgb(51, 51, 51); font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; background-color: rgb(255, 255, 255);" class="">. This would give users an implicit conversion from </span><code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; color: rgb(51, 51, 51);" class="">Substring</code><span style="color: rgb(51, 51, 51); font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; background-color: rgb(255, 255, 255);" class=""> to </span><code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; color: rgb(51, 51, 51);" class="">String</code><span style="color: rgb(51, 51, 51); font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; background-color: rgb(255, 255, 255);" class="">, as well as the usual implicit conversions such as </span><code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; color: rgb(51, 51, 51);" class="">[Substring]</code><span style="color: rgb(51, 51, 51); font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; background-color: rgb(255, 255, 255);" class=""> to </span><code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; color: rgb(51, 51, 51);" class="">[String]</code><span style="color: rgb(51, 51, 51); font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; background-color: rgb(255, 255, 255);" class=""> that other subtype relationships receive.</span></blockquote><br class=""></div><div class="">As others have said, it would be nice for this to be more general. Perhaps we can have a special type or protocol, something like RecursiveSlice?</div><div class=""><br class=""></div><div class=""><blockquote type="cite" class=""><span style="color: rgb(51, 51, 51); font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; background-color: rgb(255, 255, 255);" class="">A </span><code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; color: rgb(51, 51, 51);" class="">Substring</code><span style="color: rgb(51, 51, 51); font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; background-color: rgb(255, 255, 255);" class=""> passed where </span><code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; color: rgb(51, 51, 51);" class="">String</code><span style="color: rgb(51, 51, 51); font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; background-color: rgb(255, 255, 255);" class=""> is expected will be implicitly copied. When compared to the “same type, copied storage” model, we have effectively deferred the cost of copying from the point where a substring is created until it must be converted to </span><code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; color: rgb(51, 51, 51);" class="">String</code><span style="color: rgb(51, 51, 51); font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; background-color: rgb(255, 255, 255);" class="">for use with an API.</span></blockquote><br class=""></div><div class="">Could noescape parameters/new memory model with borrowing make this more general? Again it seems very useful for all kinds of Collections.</div><div class=""><blockquote type="cite" class=""><h5 style="box-sizing: border-box; margin-top: 24px; margin-bottom: 16px; font-size: 0.875em; line-height: 1.25; color: rgb(51, 51, 51); font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; background-color: rgb(255, 255, 255);" class="">The “Empty Subscript”</h5></blockquote><div class="">Empty subscript seems weird. IMO, it’s because of the asymmetry between subscripts and computed properties. I would favour a model which unifies computed properties and subscripts (e.g. computed properties could return “addressors” for in-place mutation).</div><div class="">Maybe this could be an “entireCollection”/“entireSlice" computed property?</div></div><div class=""><br class=""></div><div class=""><div class=""><br class=""></div></div><div class=""><blockquote type="cite" class=""><span style="color: rgb(51, 51, 51); font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; background-color: rgb(255, 255, 255);" class="">The goal is that </span><code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; color: rgb(51, 51, 51);" class="">Unicode</code><span style="color: rgb(51, 51, 51); font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; background-color: rgb(255, 255, 255);" class=""> exposes the underlying encoding and code units in such a way that for types with a known representation (e.g. a high-performance </span><code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; color: rgb(51, 51, 51);" class="">UTF8String</code><span style="color: rgb(51, 51, 51); font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; background-color: rgb(255, 255, 255);" class="">) that information can be known at compile-time and can be used to generate a single path, while still allowing types like </span><code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; color: rgb(51, 51, 51);" class="">String</code><span style="color: rgb(51, 51, 51); font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; background-color: rgb(255, 255, 255);" class=""> that admit multiple representations to use runtime queries and branches to fast path specializations.</span></blockquote><br class=""></div><div class="">Typo: “unicodeScalars" is in the protocol twice.</div><div class=""><br class=""></div><div class="">If I understand it, CodeUnits is the thing which should always be defined by conformers to Unicode, and UnicodeScalars and ExtendedASCII could have default implementations (for example, UTF8String/UTF16String/3rd party conformers will use those), and String might decide to return its native buffer (e.g. if Encoding.CodeUnit == UnicodeScalar).</div><div class=""><br class=""></div><div class="">I’m just wondering how difficult it would be for a 3rd-party type to conform to Unicode. If you’re developing a text editor, for example, it’s possible that you may need to implement your own String-like type with some optimised storage model and it would be nice to be able to use generic algorithms with them. I’m thinking that you will have some kind of backing buffer, and you will want to expose regions of that to clients as Strings so that they can render them for UI or search through them, etc, without introducing a copy just for the semantic understanding that this data region contains some text content.</div><div class=""><br class=""></div><div class="">I’ll need to examine the generic String idea more, but it’s certainly very interesting...</div><div class=""><br class=""></div><div class=""><blockquote type="cite" class="">Indexes</blockquote></div><div class=""><br class=""></div><div class="">One thing which I think it critical is the ability to advance an index by a given number of codeUnits. I was writing some code which interfaced with the Cocoa NSTextStorage class, tagging parts of a string that a user was editing. If this was an Array, when the user inserts some elements before your stored indexes, those indexes become invalid but you can easily advance by the difference to efficiently have your indexes pointing to the same characters.</div><div class=""><br class=""></div><div class="">Currently, that’s impossible with String. If the user inserts a string at a given index, your old indexes may not even point to the start of a grapheme cluster any more, and advancing the index is needlessly costly. For example:</div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><br class=""></blockquote><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><pre class="code-java" style="margin-top: 0px; margin-bottom: 0px; padding: 0px; max-height: 30em; overflow: auto; white-space: pre-wrap; word-wrap: normal;"><font face="Courier" class=""><span class="code-keyword" style="color: rgb(0, 0, 145);">var</span><font color="#333333" class=""> characters = </font><span class="code-quote"><font color="#910000" class="">"This is a test"</font></span><font color="#333333" class="">.characters
</font><span class="code-keyword" style="color: rgb(0, 0, 145);">assert</span><font color="#333333" class="">(characters.count == 14)
<br class=""></font></font></pre><pre class="code-java" style="margin-top: 0px; margin-bottom: 0px; padding: 0px; max-height: 30em; overflow: auto; white-space: pre-wrap; word-wrap: normal;"><font face="Courier" class=""><font color="#009100" class="">// Store an index to something.</font><font color="#333333" class="">
let endBeforePrepending = characters.endIndex
<br class=""></font></font></pre><pre class="code-java" style="margin-top: 0px; margin-bottom: 0px; padding: 0px; max-height: 30em; overflow: auto; white-space: pre-wrap; word-wrap: normal;"><font face="Courier" class=""><font color="#009100" class="">// Insert some characters somewhere.</font><font color="#333333" class="">
let insertedCharacters = </font><font color="#910000" class=""><span class="code-quote">"</span><span class="code-quote">[PREPENDED]</span><span class="code-quote">"</span></font><font color="#333333" class="">.characters
</font><span class="code-keyword" style="color: rgb(0, 0, 145);">assert</span><font color="#333333" class="">(insertedCharacters.count == 11)
characters.replaceSubrange(characters.startIndex..<characters.startIndex, with: insertedCharacters)
<br class=""></font></font></pre><pre class="code-java" style="margin-top: 0px; margin-bottom: 0px; padding: 0px; max-height: 30em; overflow: auto; word-wrap: normal;"><font face="Courier" color="#009100" class=""><span style="white-space: pre-wrap;" class="">// This isn’t really correct.</span></font></pre><pre class="code-java" style="margin-top: 0px; margin-bottom: 0px; padding: 0px; max-height: 30em; overflow: auto; word-wrap: normal;"><font face="Courier" class=""><font color="#333333" class=""><span style="white-space: pre-wrap;" class="">let endAfterPrepending = characters.index(endBeforePrepending, offsetBy: insertedCharacters.count)
</span></font><span class="code-keyword" style="color: rgb(0, 0, 145); white-space: pre-wrap;">assert</span><font color="#333333" class=""><span style="white-space: pre-wrap;" class="">(endAfterPrepending == characters.endIndex) </span></font><span class="code-comment" style="color: rgb(128, 128, 128); white-space: pre-wrap;">// Fails Anyway. 24 != 25</span></font></pre><div class=""><br class=""></div></blockquote><div class=""><br class=""></div><div class="">The manifesto is correct to emphasise machine processing of Strings, but it should also ensure that machine processing of mutable Strings is efficient. That way we can tag backing-Strings inside user-interface components and maintain those indices in a unicode-safe way.</div><div class=""><br class=""></div><div class="">The way to solve this would be that, when replacing or removing a portion of a String, you learn how many CodeUnits in the receiver’s encoding were inserted/removed so you can shift your indexes accordingly.</div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><br class=""></div></body></html>