Slice

A view into a subsequence of elements of another collection.

@frozen struct Slice<Base> where Base : Collection

A slice stores a base collection and the start and end indices of the view. It does not copy the elements from the collection into separate storage. Thus, creating a slice has O(1) complexity.

Slices Share Indices

Indices of a slice can be used interchangeably with indices of the base collection. An element of a slice is located under the same index in the slice and in the base collection, as long as neither the collection nor the slice has been mutated since the slice was created.

For example, suppose you have an array holding the number of absences from each class during a session.

var absences = [0, 2, 0, 4, 0, 3, 1, 0]

You’re tasked with finding the day with the most absences in the second half of the session. To find the index of the day in question, follow these steps:

  1. Create a slice of the absences array that holds the second half of the days.

  2. Use the max(by:) method to determine the index of the day with the most absences.

  3. Print the result using the index found in step 2 on the original absences array.

Here’s an implementation of those steps:

let secondHalf = absences.suffix(absences.count / 2)
if let i = secondHalf.indices.max(by: { secondHalf[$0] < secondHalf[$1] }) {
    print("Highest second-half absences: \(absences[i])")
}
// Prints "Highest second-half absences: 3"

Slices Inherit Semantics

A slice inherits the value or reference semantics of its base collection. That is, if a Slice instance is wrapped around a mutable collection that has value semantics, such as an array, mutating the original collection would trigger a copy of that collection, and not affect the base collection stored inside of the slice.

For example, if you update the last element of the absences array from 0 to 2, the secondHalf slice is unchanged.

absences[7] = 2
print(absences)
// Prints "[0, 2, 0, 4, 0, 3, 1, 2]"
print(secondHalf)
// Prints "[0, 3, 1, 0]"

Use slices only for transient computation. A slice may hold a reference to the entire storage of a larger collection, not just to the portion it presents, even after the base collection’s lifetime ends. Long-term storage of a slice may therefore prolong the lifetime of elements that are no longer otherwise accessible, which can erroneously appear to be memory leakage.