Почему popFirst выдает ошибку, а removeFirst работает?

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, и removeFirst помечены как mutating и оба возвращаются и T?. Так почему это не работает?

Обновлено: Как отмечали другие, это похоже на какую-то ошибку. Обсуждалось на форумах здесь.

Обновлено: По-прежнему происходит в Xcode 9.4.1 (Swift 4.1.2)

К вашему сведению - removeFirst возвращает T, а не T?.

rmaddy 09.04.2018 01:23

Похоже на ошибку. Даже var a = [1,2,3]; let first = a.popFirst() дает такую ​​же ошибку.

vacawama 09.04.2018 01:36

Я не уверен, почему вы получаете именно эту ошибку, но ссылка, которую вы отправили для popFirst, предназначена для ArraySlice, а не для Array. Если вы создаете ArraySlice, он отлично работает, например var a = ArraySlice(elements); let foo = a.popFirst()

daltonclaybrook 09.04.2018 02:19
Структурированный массив Numpy
Структурированный массив Numpy
Однако в реальных проектах я чаще всего имею дело со списками, состоящими из нескольких типов данных. Как мы можем использовать массивы numpy, чтобы...
T - 1Bits: Генерация последовательного массива
T - 1Bits: Генерация последовательного массива
По мере того, как мы пишем все больше кода, мы привыкаем к определенным способам действий. То тут, то там мы находим код, который заставляет нас...
Что такое деструктуризация массива в JavaScript?
Что такое деструктуризация массива в JavaScript?
Деструктуризация позволяет распаковывать значения из массивов и добавлять их в отдельные переменные.
9
3
1 258
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 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. Вот реализация:

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 == Self, потому что self[index(after: startIndex)..<endIndex] возвращает SubSequence, который нельзя присвоить self, если только Self (конкретный тип, соответствующий Collection) и его SubSequence не относятся к тому же типу.

Тип ArraySubSequence - это ArraySlice, а не Array, поэтому это расширение не применяется к Array.

Вот расширение, которое вы, вероятно, ищете:

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

вам следует расширить RangeReplaceableCollection вместо Array extension RangeReplaceableCollection {@inlinablepublic mutating func popFirst() -> Element? {guard !isEmpty else {return nil} return removeFirst ()}} `

Leo Dabus 26.09.2020 20:32

Другие вопросы по теме