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

标签 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 的新行为吗?我该如何解决?

最佳答案

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
  }
}

您会注意到它受到约束,CollectionSubSequence 就是它本身。对于 String(以及许多其他集合类型,例如 ArraySet),情况并非如此;但对于这些类型的切片来说是正确的。

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/

相关文章:

ios - Xcode 7.1 中没有 "Run in Full Simulator"的 UIView 动画?

ios - 根据 subview 以编程方式设置 View 宽度大小

ios - 如何在文本字段中允许和获取拟我表情贴纸

ios - 可以在 Swift 项目中使用 libVLC 吗?

Swift delegate 在 uiviewcontroller 和 uitableviewcontroller 之间进行通信

ios - 快速使用 WhirlyGlobe-Maply

swift - 无法将类型 'child' 的返回表达式转换为返回类型 T

ios - 尝试触发 UILocalNotification 不起作用

Swift Firebase 函数错误 : NSCocoaErrorDomain

ios - 在更新期间更改 UITableViewCells 时 swift 崩溃