Is there any difference at all between suffix(from:) and dropFirst(_:)?

subsequence, swift, swift3

Solution

They are completely different.

`suffix(from:)`

- Defined by the `Collection` protocol.

- Returns a `Subsequence` from a given starting `Index`.

- Documented time complexity of O(1) (you can see its default implementation here).

- Runtime error if the index you pass is out of range.

`dropFirst(_:)`

- Defined by the `Sequence` protocol.

- Returns a `SubSequence` with a given maximum number of elements removed from the head of the sequence.

- Has a documented time complexity of O(n)*. Although its default implementation actually has a time complexity of O(1), this just postpones the O(n) walk through the dropped elements until iteration.

- Returns an empty subsequence if the number you input is greater than the sequence's length.

*As with all protocol requirement documented time complexities, it's possible for the conforming type to have an implementation with a lower time complexity. For example, a `RandomAccessCollection`'s `dropFirst(_:)` method will run in O(1) time.

However, when it comes to `Array`, these methods just happen to behave identically (except for the handling of out of range inputs).

This is because `Array` has an `Index` of type `Int` that starts from `0` and sequentially counts up to `array.count - 1`, therefore meaning that a subsequence with the first `n` elements dropped is the same subsequence that starts from the index `n`.

Also because `Array` is a `RandomAccessCollection`, both methods will run in O(1) time.

Problem

It just occurred to me that when working with subsequences in Swift, `func suffix(from: Int)` seems to be identical to just `dropFirst(_:)` (Obviously, you just change the input value from say "3" to "7" in the case of an array of length "10".) Just to repeat that. So: of course, for an array of say length ten. What I mean is `func suffix(from: Int)` with "2" would be the same as `dropFirst(_:)` with "8", for example. Similarly `upTo` / `through` seem to be identical to `dropLast(_:)` Other than convenience is there any difference at all? (Perhaps in error conditions, performance, or?) I was wondering whether, in fact, inside Swift one or the other is just implemented by calling the other?

Original source