考虑这个假设的 Swift 函数:
func putFirst(_ string: String) {
var str = string
let c = str.popFirst()
print(c)
}
我预计,基于之前的问题,例如 this one , str
是一个变量,因此是可变的。但是,str.popFirst()
会抛出一个编译错误,
Cannot use mutating member on immutable value: 'str' is immutable
这是我没有意识到的微妙之处吗?它是 Swift 4 的新行为吗?我该如何解决?
最佳答案
是a useless error message ;问题是 Collection
上只定义了一个 popFirst()
方法。 Here it is :
extension Collection where SubSequence == Self { /// Removes and returns the first element of the collection. /// /// - Returns: The first element of the collection if the collection is /// not empty; otherwise, `nil`. /// /// - Complexity: O(1) @_inlineable public mutating func popFirst() -> Element? { // TODO: swift-3-indexing-model - review the following guard !isEmpty else { return nil } let element = first! self = self[index(after: startIndex)..<endIndex] return element } }
您会注意到它受到约束,Collection
的 SubSequence
就是它本身。对于 String
(以及许多其他集合类型,例如 Array
和 Set
),情况并非如此;但对于这些类型的切片来说是正确的。
RangeReplaceableCollection
上没有不受约束的 popFirst()
重载(String
符合)。这样做的原因,as given by Dave Abrahams in this bug report , popFirst()
应该是 O(1);并且 RangeReplaceableCollection
上的实现不能保证这一点(实际上对于 String
,它是线性时间)。
反对这个的另一个很好的理由,as mentioned by Leo Dabus ,这是 popFirst()
不会使集合的索引无效。 RRC 上的实现无法保证这一点。
因此,由于完全不同的语义,不期望 RRC 上的 popFirst()
过载是非常合理的。不过,您始终可以为此在 RRC 上定义一个不同名称的便捷方法:
extension RangeReplaceableCollection {
/// Removes and returns the first element of the collection.
///
/// Calling this method may invalidate all saved indices of this
/// collection. Do not rely on a previously stored index value after
/// altering a collection with any operation that can change its length.
///
/// - Returns: The first element of the collection if the collection is
/// not empty; otherwise, `nil`.
///
/// - Complexity: O(n)
public mutating func attemptRemoveFirst() -> Element? {
return isEmpty ? nil : removeFirst()
}
}
然后你会说:
func putFirst(_ string: String) {
var str = string
let c = str.attemptRemoveFirst()
print(c)
}
关于swift - 在 Swift 中将常量字符串转换为变量字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46761165/