在Swift中将常量字符串转换为变量字符串

时间:2017-10-15 23:46:13

标签: swift

考虑这个假设的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的新行为吗?我该如何解决这个问题?

1 个答案:

答案 0 :(得分:1)

它的a useless error message;问题是Collection上只定义了一个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 } } 方法。 Here it is

Collection

您会注意到它受到限制,SubSequence String本身就是这样。对于Array(以及SetpopFirst()等许多其他集合类型),情况并非如此;但对于那些类型的切片都是如此。

RangeReplaceableCollection String上没有popFirst()的无约束重载(RangeReplaceableCollection符合)。对此的推理as given by Dave Abrahams in this bug reportString应为O(1);并且popFirst()上的实现无法保证(实际上对于popFirst(),它是线性时间)。

反对这一点的另一个好理由as mentioned by Leo Dabus,就是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() } } 不会使集合的索引无效。 RRC的实施无法保证这一点。

因此,由于语义差别很大,不期望RRC上的func putFirst(_ string: String) { var str = string let c = str.attemptRemoveFirst() print(c) } 过载是非常合理的。尽管如此,你总是可以在RRC上定义一个不同名称的便捷方法:

{{1}}

然后你会说:

{{1}}