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()
}
}
The error I get for popFirst
is:
cannot use mutating member on immutable value: 'self' is immutable
Both popFirst
and removeFirst
are marked as mutating
and both return and T?
. So why isn't it working?
EDIT: As others have commented, it seems to be some sort of bug. It's been discussed in the forums here.
EDIT: Still happens in Xcode 9.4.1 (Swift 4.1.2)
The error is improved in 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!
^
You get the error because popFirst
is not defined for all Collection
s. It's only defined if the Collection
is its own SubSequence
type. 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
}
}
The extension requires SubSequence == Self
. Self
(with a capital S) is the type of self
(with a lower-case s). It is the type on which you're calling popFirst
. In your code, Self
is Array<T>
, also spelled [T]
.
The constraint is necessary for this line of popFirst
to compile:
self = self[index(after: startIndex)..<endIndex] ^__^ ^_______________________________________^ | | | This is a SubSequence. | This is a Self.
self[index(after: startIndex)..<endIndex]
is a SubSequence
.
Swift can only assign a SubSequence
to Self
if it knows that Self == SubSequence
.
Array
's SubSequence
type is ArraySlice
. Since ArraySlice
is not the same type as Array
, this extension doesn't apply to Array
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With