Why does the reverse() function in the Swift standard library return ReverseRandomAccessCollection? Why does the reverse() function in the Swift standard library return ReverseRandomAccessCollection? arrays arrays

Why does the reverse() function in the Swift standard library return ReverseRandomAccessCollection?


It is an performance optimization for both time and memory. The ReverseRandomAccessCollection presents the elements of theoriginal array in reverse order, without the need to create a new arrayand copying all elements (as long as the original array is notmutated).

You can access the reversed elements with subscripts:

let el0 = arr[arr.startIndex]let el2 = arr[arr.startIndex.advancedBy(2)]

or

for i in arr.indices {    print(arr[i])}

You can also create an array explicitly with

let reversed = Array(["Mykonos", "Rhodes", "Naxos"].reversed())

A dictionary is also a sequence of Key/Value pairs. In

let dict = ["greek" : "swift sometimes", "notgreek" : "ruby for this example"].reverse()

a completely different reversed() method is called:

extension SequenceType {    /// Return an `Array` containing the elements of `self` in reverse    /// order.    ///    /// Complexity: O(N), where N is the length of `self`.    @warn_unused_result    public func reversed() -> [Self.Generator.Element]}

The result is an array with the Key/Value pairs of the dictionaryin reverse order. But this is of limited use because the orderof the Key/Value pairs in a dictionary can be arbitrary.


From the language docs of ReverseCollention (result of .reverse()):

The reverse() method is always lazy when applied to a collection with bidirectional indices, but does not implicitly confer laziness on algorithms applied to its result.

In other words, for ordinary collections c having bidirectional indices:

  • c.reverse() does not create new storage

...

Hence, you could see your ReverseRandomAccessCollection as a random access wrapper over your not yet reversed array (i.e., your original array arr has not yet been copied and reversed to a new position in memory).

Naturally, from the above, you can't index the reverse collection directly, as an Array gives access as a pointer to the memory that holds the array, and indexing corresponds to proceeding bitwise (depending on type) forward in memory. We can still, however, access the elements of the "reverse array" in array index style using ReverseRandomAccessIndex:

let arr = ["Mykonos", "Rhodes", "Naxos"]let arrReverse = arr.reverse()    /* ReverseRandomAccessCollection access "wrapper" over       the 'arr' data in memory. No new storage allocated */let myIndex = arrReverse.startIndex.advancedBy(2)    /* bIndex type:        ReverseRandomAccessIndex<ReverseRandomAccessIndex<Index>> */print(arrReverse[myIndex]) // "Mykonos"

Conversely, we can explicitly allocate memory for our reverse array, and treat it just as any other array. At this point, the arrReverse is a separate array than arr, and holds no relation to the former other than (once) being created by using it.

let arr = ["Mykonos", "Rhodes", "Naxos"]let arrReverse = Array(arr.reverse())    /* Array<String> */let myIndex = arrReverse.startIndex.advancedBy(2)    /* bIndex type: Int */print(arrReverse[myIndex]) // "Mykonos"

Martin R beat me to it, so see his note regarding the dictionaries.


With Swift 3.0, you can directly access the Array value through index.

var streets = ["Albemarle", "Brandywine", "Chesapeake"]streets = streets.reversed()print("Array at index is \(streets[0])")

This will print "Chesapeake"