dropLast
is indeed overloaded here; specifically, you're seeing the difference between
-
Sequence.dropLast(_:)
, which returns an explicitly-typed[Self.Element]
, and -
BidirectionalCollection.dropLast(_:)
, which returnsSelf.SubSequence
Array
conforms to both protocols, so without explicit typing, either one can get called, which may be unfortunate. To answer your questions:
- The overload exists because this is a useful operation, but
Sequence
s can't be sliced. The only way for the operation to exist is for something to collect the results of iterating theSequence
and drop the lastN
elements on the floor - No, the
Sequence
version of the method isO(n)
, which means that reassigningarray = array.dropLast(1)
goes through anO(n)
copy, which you'll want to avoid. Yes, this is subtle!- It may be possible for the
Sequence
implementation to optimize this by checking ifSelf == Array
and using someArray
internals to avoid a copy via CoW, but I don't know the specifics off the top of my head, and it simply doesn't do this at the moment
- It may be possible for the
- We don't need an overload for
dropFirst
, sinceSequence.dropFirst(_:)
can already drop the firstN
element in the sequence (by iterating forward and ignoring the results) in "O(1)
" time
This situation is very similar to Is Swift array reversed()[n] efficient or not? - Stack Overflow and Missed optimization in ReversedCollection?