Swift字符串和整数下标

sim*_*one 2 string swift swift4

这是一个理论问题

为什么以下(以及更多类比)不是Swift标准库的一部分?什么是坏情况

extension String {
    subscript(_ range: Range<Int>) -> Substring {
        return self[index(startIndex, offsetBy: range.lowerBound)..<index(startIndex, offsetBy: range.upperBound)]
    }
}

extension Substring {
    subscript(_ range: Range<Int>) -> Substring {
        return self[index(startIndex, offsetBy: range.lowerBound)..<index(startIndex, offsetBy: range.upperBound)]
    }
}
Run Code Online (Sandbox Code Playgroud)

Rob*_*ier 5

为了扩展Hamish的观点,这将是非常令人惊讶的行为.让我们考虑更简单(但相当)的情况string[int],这将构建于此基础之上.为什么不用int来下标字符串.

字符串是字符的集合,而不是字节.它们可以存储在UTF-8中,这意味着你不知道一个角色有多大,你不能只跳到任意位置.为了弄清楚"角色100"你必须从头开始并解码一切.那是O(n).

所以你编写这样的代码,感觉非常"安全":

for index in 0..<string.count {
    print(string[index])
}
Run Code Online (Sandbox Code Playgroud)

但是暗地说这是O(n ^ 2),这真的很令人惊讶,因为它确实看起来像O(n).你可能会说"好吧,我的字符串长度只有20个字符,所以谁在乎",但我们为很多东西编写了字符串,包括多兆字节NSTextStorage.(并且这在Swift中与其他语言相比有很大的扩展,因为Swift包含通用算法,其性能承诺依赖于下标为O(1)的事实.)

因此,我可以让事情变得"轻松",直到突然事情变得非常困难,当你关心性能的时候.(而且我并不是说"超级快"中的"表现".我的意思是"表现",因为"不会让整个应用程序停止运转几分钟."

具有"简单"索引的语言是"简单的",因为它们忽略了Unicode.所以一切都很好,直到你得到一个表情符号,它都爆炸,你必须编写疯狂的讨厌的代码来解决它.Swift决定像表情符号(和中文,阿拉伯语,泰语和......)这样的东西是非常正常的东西放在一个字符串中,所以应该作为一流处理,而不是在事情爆炸时解决.

如果你想研究的是去了另一条路语言,看看去,这对串的"符文"系统,该系统是很难得到正确的瞬间表情符号显示出来.Go的回答是"当可能存在多字节字符时,程序员应该做正确的事情." 斯威夫特的回答是"语言应该始终做正确的事情." 两者都有合理的论点,但Swift的方法避免了很多现实世界的错误(比如我在ObjC工作时意外截断多字节密码时为我的中国用户引入的可怕安全问题).