<div dir="ltr"><div class="gmail_default"><font face="georgia, serif">Thanks a lot, Ole. I understand now.</font></div><div class="gmail_default"><font face="georgia, serif"><br></font></div><div class="gmail_default"><font face="georgia, serif">Zhaoxin</font></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Mar 9, 2017 at 7:54 PM, Ole Begemann <span dir="ltr">&lt;<a href="mailto:ole@oleb.net" target="_blank">ole@oleb.net</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">On 09/03/2017 08:27, Zhao Xin via swift-users wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
When using subscript of `String.CharacterView`, I got an unexpected error.<br>
<br>
    fatal error: Can&#39;t form a Character from an empty String<br>
<br>
func test() {<br>
    let s = &quot;Original Script:&quot;<br>
    let cs = s.characters<br>
//    let startIndex = cs.startIndex<br>
    let nextIndex = &quot;Original ?&quot;.characters.endIndex<br>
    let nextCharacter = cs[nextIndex]// above error<br>
}<br>
<br>
test()<br>
</blockquote>
<br></span>
First of all, it&#39;s not guaranteed that an index derived from one string can be used to subscript another string. Don&#39;t rely on that.<br>
<br>
endIndex is also different, and this is why you&#39;re seeing a crash here. Let&#39;s inspect nextIndex with dump(nextIndex):<br>
<br>
▿ Swift.String.CharacterView.Ind<wbr>ex<br>
  ▿ _base: Swift.String.UnicodeScalarView<wbr>.Index<br>
    - _position: 10<br>
  - _countUTF16: 0<br>
<br>
You see that _countUTF16 is 0, i.e. internally, String.CharacterView assigns its endIndex a length of 0 (in terms of UTF-16 code units). This is why it traps when you use the index for subscripting. The endIndex is not a valid index for subscripting, not for the string it was derived from and not for any other string.<span class=""><br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
​However, if I chose​ another way to get the nextIndex. It works.<br>
<br>
functest() {<br>
    let s = &quot;Original Script:&quot;<br>
    let cs = s.characters<br>
    let startIndex = cs.startIndex<br>
//    let nextIndex = &quot;Original ?&quot;.characters.endIndex<br>
    let nextIndex01 = cs.index(startIndex, offsetBy: &quot;Original<br>
?&quot;.characters.count)<br>
    let nextCharacter = cs[nextIndex01]<br>
}<br>
<br>
test()<br>
</blockquote>
<br></span>
Here, dump(nextIndex01) prints this:<br>
<br>
▿ Swift.String.CharacterView.Ind<wbr>ex<br>
  ▿ _base: Swift.String.UnicodeScalarView<wbr>.Index<br>
    - _position: 10<br>
  - _countUTF16: 1<br>
<br>
Notice that _countUTF16 is 1, so it looks like a valid index from the perspective of cs. But again, don&#39;t rely on this! The results of subscripting a collection with an index derived from another collection are undefined unless the collection explicitly documents otherwise.<span class=""><br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Further more, I compared the two `nextIndex`. They were equal.<br>
<br>
functest() {<br>
    let s = &quot;Original Script:&quot;<br>
    let cs = s.characters<br>
    let startIndex = cs.startIndex<br>
    let nextIndex = &quot;Original ?&quot;.characters.endIndex<br>
    let nextIndex01 = cs.index(startIndex, offsetBy: &quot;Original<br>
?&quot;.characters.count)<br>
    let nextCharacter = cs[nextIndex01]<br>
    print(nextIndex01 == nextIndex) // true<br>
}<br>
<br>
test()<br>
</blockquote>
<br></span>
It looks like String.Index only takes the position into account to determine equality, not its _countUTF16. This makes sense for the way endIndex and index(_:offsetBy:) are implemented. After all, nextIndex and nextIndex01 _should be equal_. It would certainly be possible to implement it differently (where endIndex and index(_:offsetBy:) returned identical indices, including _countUTF16:) and I don&#39;t know why the stdlib team chose to do it this way (maybe performance?).<br>
<br>
In any case, much of this implementation may change with the work going into strings for Swift 4.<br>
<br>
<br>
</blockquote></div><br></div>