这是一个理论问题
为什么以下(以及更多类比)不是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)]
}
}
答案 0 :(得分:5)
为了扩展哈米什的观点,这将是非常令人惊讶的行为。让我们考虑string[int]
的更简单(但相当)的情况,这将构建于此基础之上。为什么不用ints下标字符串。
字符串是字符的集合,而不是字节。它们可以存储在UTF-8中,这意味着你不知道一个角色有多大,而且你不能只跳到任意位置。为了弄清楚“角色100”你必须从头开始并解码一切。那是O(n)。
所以你编写这样的代码,感觉非常“安全”:
for index in 0..<string.count {
print(string[index])
}
但是秘密地说这是O(n ^ 2),这确实令人惊讶,因为它确实看起来像O(n)。你可能会说“嗯,我的字符串长度只有20个字符,所以谁关心”,但我们为许多事情编写了字符串,包括多兆字节NSTextStorage
。 (并且这在Swift中与其他语言相比有很大的扩展,因为Swift包含通用算法,其性能承诺依赖于下标为O(1)的事实。)
所以我可以为你做一些“容易”的事情,直到事情变得非常困难,当你关心性能的时候。 (而且我并不是说“超级快”中的“表现”。我的意思是“表现”,如“不会让整个应用程序暂停几分钟。”
“简单”索引的语言“简单”,因为它们忽略了Unicode。所以一切都很好,直到你得到一个表情符号,它都爆炸,你必须编写疯狂的讨厌的代码来解决它。 Swift决定像表情符号(和中文,阿拉伯语,泰语和......)这样的东西是非常正常的东西放在一个字符串中,所以应该作为一流处理,而不是在事情爆炸时解决。
如果你想学习一种其他方式的语言,那就看看Go,它有一个“符文”系统,用于在表情符号出现的那一刻很难正确使用的字符串。 Go的回答是“当可能存在多字节字符时,程序员应该做正确的事情。”斯威夫特的回答是“语言应该始终做正确的事情。”两者都有合理的论据,但Swift的方法避免了很多现实世界的错误(比如我在ObjC工作时意外截断多字节密码时为我的中国用户引入的可怕安全问题)。