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)
Похоже на ошибку. Даже var a = [1,2,3]; let first = a.popFirst() дает такую же ошибку.
Я не уверен, почему вы получаете именно эту ошибку, но ссылка, которую вы отправили для popFirst, предназначена для ArraySlice, а не для Array. Если вы создаете ArraySlice, он отлично работает, например var a = ArraySlice(elements); let foo = a.popFirst()



Ошибка улучшена в 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 ()}} `
К вашему сведению -
removeFirstвозвращаетT, а неT?.