Why doesn't dropFirst return an array, but dropLast does?

Viewed 358

This function builds successfully

func dropLastFromArray(_ array: [Any]) -> [Any] {
    return array.dropLast()
}

but this function does not

func dropFirstFromArray(_ array: [Any]) -> [Any] {
    return array.dropFirst()
}

it gives a build error: No 'dropFirst' candidates produce the expected contextual result type '[Any]'

What is going on? In the docs, they both show a return type of ArraySlice<Element>. It seems to me that one of these two must be wrong.

I'm using XCode 12.5.1 if that matters

2 Answers

Both your declarations are wrong; both dropFirst and dropLast return an ArraySlice, not an Array.

The reason that the dropLast example doesn't complain in the same way as the dropFirst example is that there is another dropLast, namely Sequence dropLast:

https://developer.apple.com/documentation/swift/sequence/3128805-droplast

Failing to find an Array dropLast that works for your code, the compiler falls back on the Sequence dropLast, because an Array is also a Sequence.

The difference you are experiencing is in fact thus reflecting the way Sequence dropFirst and dropLast differ from one another. The former returns a DropFirstSequence, whereas the latter returns an Array. And you can see why. Dropping the last element is trivial: we just shorten the sequence count by one. But to drop the first element would be a big deal if we had to throw away the first element and renumber all the elements, so we don't; we use a special type that keeps the original sequence and just ignores the first element.

I think the documentation might be wrong, if you [option]+[click] on both dropFirst and dropLast, they state that they return different things

dropFirst is reported as returning ArraySlice<Any>, but dropLast is reported as returning [Any]

DropFirst

DropLast

Why this is done is probably a performance issue, but I'm speculating, and, yes, I find it very annoying to

Related