为什么 popFirst 抛出错误,但 removeFirst 有效?

Why popFirst throws an error, but removeFirst works?

struct Queue<T>{

    private var elements : [T] = []

    public mutating func enqueue(_ element: T){
        elements.append(element)
    }
    public mutating func dequeue() -> T?{
        return elements.popFirst()  // ERROR!
    }
    public mutating func dequeue2() -> T?{
        return elements.removeFirst()
    }
}

我得到的 popFirst 错误是:

cannot use mutating member on immutable value: 'self' is immutable

popFirst and removeFirst 都标记为 mutating,return 和 T?。那为什么它不起作用?

编辑: 正如其他人评论的那样,这似乎是某种错误。它已在论坛 here.

中讨论过

编辑: 仍然发生在 Xcode 9.4.1 (Swift 4.1.2)

错误在Swift 4.2:

中得到改善
error: ios.playground:4:25: error: '[T]' requires the types '[T]' and 'ArraySlice<T>' be equivalent to use 'popFirst'
        return elements.popFirst()  // ERROR!
                        ^

你得到这个错误是因为 popFirst 没有为所有 Collection 定义。它仅在 Collection 是它自己的 SubSequence 类型时定义。 Here's the implementation:

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)
  @inlinable
  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
  }
}

扩展需要 SubSequence == SelfSelf(大写 S)是 self(小写 s)的类型。这是您要调用的类型 popFirst。在您的代码中,SelfArray<T>,也拼写为 [T]

popFirst这一行编译需要约束:

self = self[index(after: startIndex)..<endIndex]

^__^   ^_______________________________________^
 |                         |
 |                        This is a SubSequence.
 |
This is a Self.

self[index(after: startIndex)..<endIndex]SubSequence.

Swift如果知道Self == SubSequence.

只能将SubSequence赋值给Self

ArraySubSequence 类型是 ArraySlice。由于 ArraySliceArray 不是同一类型,因此此扩展不适用于 Array

您可能正在寻找的扩展程序如下:

extension Array {
    @inlinable
    public mutating func popFirst() -> Element? {
        if isEmpty {
            return nil
        } else {
            return removeFirst()
        }
    }
}