:orphan:

.. @raise litre.TestsAreMissing
.. default-role:: code

====================================
 Sequences And Collections in Swift
====================================

Unlike many languages, Swift provides a rich taxonomy of abstractions
for processing series of elements.  This document explains why that
taxonomy exists and how it is structured.

Sequences
=========

It all begins with Swift's `for`\ …\ `in` loop::

  for x in s {
    doSomethingWith(x)
  }

Because this construct is generic, `s` could be

* an array
* a set
* a linked list
* a series of UI events
* a file on disk
* a stream of incoming network packets
* an infinite series of random numbers
* a user-defined data structure
* etc.

In Swift, all of the above are called **sequences**, an abstraction
represented by the `SequenceType` protocol::

  protocol SequenceType {
    typealias Iterator : IteratorProtocol
    func makeIterator() -> Iterator
  }

.. sidebar:: Hiding Iterator Type Details

  A sequence's iterator is an associated type—rather than something
  like |AnyIterator|__ that depends only on the element type—for
  performance reasons.  Although the alternative design has
  significant usability benefits, it requires one dynamic
  allocation/deallocation pair and *N* dynamic dispatches to traverse
  a sequence of length *N*.  That said, our optimizer has improved to
  the point where it can sometimes remove these overheads completely,
  and we are `considering <rdar://19755076>`_ changing the design
  accordingly.

  .. |AnyIterator| replace:: `AnyIterator<T>`

  __ http://swiftdoc.org/v3.0/type/AnyIterator/

As you can see, sequence does nothing more than deliver an iterator.
To understand the need for iterators, it's important to distinguish
the two kinds of sequences.

* **Volatile** sequences like "stream of network packets," carry
  their own traversal state, and are expected to be "consumed" as they
  are traversed.

* **Stable** sequences, like arrays, should *not* be mutated by `for`\
  …\ `in`, and thus require *separate traversal state*.

To get an initial traversal state for an arbitrary sequence `x`, Swift
calls `x.makeIterator()`.  The sequence delivers that state, along with
traversal logic, in the form of an **iterator**.

Iterators
==========

`for`\ …\ `in` needs three operations from the iterator:

* get the current element
* advance to the next element
* detect whether there are more elements

If we literally translate the above into protocol requirements, we get
something like this::

  protocol NaiveIteratorProtocol {
    typealias Element
    var current() -> Element      // get the current element
    mutating func advance()       // advance to the next element       
    var isExhausted: Bool         // detect whether there are more elements
  }

Such a protocol, though, places a burden on implementors of volatile
sequences: either the iterator must buffer the current element
internally so that `current` can repeatedly return the same value, or
it must trap when `current` is called twice without an intervening
call to `moveToNext`.  Both semantics have a performance cost, and
the latter unnecessarily adds the possibility of incorrect usage.

.. sidebar:: `NSEnumerator`

  You might recognize the influence on iterators of the `NSEnumerator` API::

    class NSEnumerator : NSObject {
      func nextObject() -> AnyObject?
    }

Therefore, Swift's `IteratorProtocol` merges the three operations into one,
returning `nil` when the iterator is exhausted::

  protocol IteratorProtocol {
    typealias Element
    mutating func next() -> Element?
  }

Combined with `SequenceType`, we now have everything we need to
implement a generic `for`\ …\ `in` loop.

.. sidebar:: Adding a Buffer

  The use-cases for singly-buffered iterators are rare enough that it
  is not worth complicating `IteratorProtocol`, [#input_iterator]_ but
  support for buffering would fit nicely into the scheme, should it
  prove important::

    public protocol BufferedIteratorProtocol 
      : IteratorProtocol {
      var latest: Element? {get}
    }

  The library could easily offer a generic wrapper that adapts any
  `IteratorProtocol` to create a `BufferedIteratorProtocol`::

    /// Add buffering to any IteratorProtocol I
    struct BufferedIterator<I : IteratorProtocol>
      : BufferedIteratorProtocol {

      public init(_ baseIterator: I) {
        self._baseIterator = baseIterator
      }
      public func next() -> Element? {
        latest = _baseIterator.next() ?? latest
        return latest 
      }
      public private(set) var latest: I.Element?
      private var _baseIterator: I
    }

Operating on Sequences Generically
----------------------------------

Given an arbitrary `SequenceType`, aside from a simple `for`\ …\ `in` loop,
you can do anything that requires reading elements from beginning to
end.  For example::

  // Return an array containing the elements of `source`, with
  // `separator` interposed between each consecutive pair.
  func array<S: SequenceType>(
    _ source: S, 
    withSeparator separator: S.Iterator.Element
  ) -> [S.Iterator.Element] {
    var result: [S.Iterator.Element] = []
    var iterator = source.makeIterator()
    if let start = iterator.next() {
      result.append(start)
      while let next = iterator.next() {
        result.append(separator)
        result.append(next)
      }
    }
    return result
  }

  let s = String(array("Swift", withSeparator: "|"))
  print(s)        // "S|w|i|f|t"

Because sequences may be volatile, though, you can—in general—only
make a single traversal.  This capability is quite enough for many
languages: the iteration abstractions of Java, C#, Python, and Ruby
all go about as far as `SequenceType`, and no further.  In Swift,
though, we want to do much more generically.  All of the following
depend on stability that an arbitrary sequence can't provide:

* Finding a sub-sequence
* Finding the element that occurs most often
* Meaningful in-place element mutation (including sorting,
  partitioning, rotations, etc.)

.. sidebar:: Iterators Should Be Sequences

  In principle, every iterator is a volatile sequence containing
  the elements it has yet to return from `next()`.  Therefore, every
  iterator *could* satisfy the requirements of `SequenceType` by
  simply declaring conformance, and returning `self` from its
  `makeIterator()` method.  In fact, if it weren't for `current language
  limitations <rdar://17986597>`_, `IteratorProtocol` would refine
  `SequenceType`, as follows:

  .. parsed-literal::

       protocol IteratorProtocol **: SequenceType** {
         typealias Element
         mutating func next() -> Element?
       }

  Though we may not currently be able to *require* that every
  `IteratorProtocol` refines `SequenceType`, most iterators in the
  standard library do conform to `SequenceType`.

Fortunately, many real sequences *are* stable. To take advantage of
that stability in generic code, we'll need another protocol.

Collections
===========

A **collection** is a stable sequence with addressable "positions,"
represented by an associated `Index` type::
 
  protocol CollectionType : SequenceType {
    typealias Index : ForwardIndexType             // a position
    subscript(i: Index) -> Iterator.Element {get}

    var startIndex: Index {get}
    var endIndex: Index {get}
  }

The way we address positions in a collection is a generalization of
how we interact with arrays: we subscript the collection using its
`Index` type::

  let ith = c[i]

An **index**\ —which must model `ForwardIndexType`\ —is a type with a
linear series of discrete values that can be compared for equality:

.. sidebar:: Dictionary Keys

   Although dictionaries overload `subscript` to also operate on keys,
   a `Dictionary`\ 's `Key` type is distinct from its `Index` type.
   Subscripting on an index is expected to offer direct access,
   without introducing overheads like searching or hashing.

::

  protocol ForwardIndexType : Equatable {
    typealias Distance : SignedIntegerType
    func successor() -> Self
  }

While one can use `successor()` to create an incremented index value,
indices are more commonly advanced using an in-place increment
operator, just as one would when traversing an array: `++i` or `i++`.
These operators are defined generically, for all models of
`ForwardIndexType`, in terms of the `successor()` method.

Every collection has two special indices: a `startIndex` and an
`endIndex`.  In an empty collection, `startIndex == endIndex`.
Otherwise, `startIndex` addresses the collection's first element, and
`endIndex` is the successor of an index addressing the collection's
last element.  A collection's `startIndex` and `endIndex` form a
half-open range containing its elements: while a collection's
`endIndex` is a valid index value for comparison, it is not a valid
index for subscripting the collection::

  if c.startIndex != c.endIndex { } // OK
  c[c.endIndex]                     // Oops! (index out-of-range)

Mutable Collections
-------------------

A **mutable collection** is a collection that supports in-place element
mutation.  The protocol is a simple refinement of `CollectionType` that adds a
subscript setter:

.. parsed-literal::

  protocol MutableCollectionType : CollectionType {
    subscript(i: Index) -> Iterator.Element { get **set** }
  }

The `CollectionType` protocol does not require collection to support mutation,
so it is not possible to tell from the protocol itself whether the order of
elements in an instance of a type that conforms to `CollectionType` has a
domain-specific meaning or not.  (Note that since elements in collections have
stable indices, the element order within the collection itself is stable; the
order sometimes does not have a meaning and is not chosen by the code that uses
the collection, but by the implementation details of the collection itself.)

`MutableCollectionType` protocol allows the to replace a specific element,
identified by an index, with another one in the same position.  This capability
essentially allows to rearrange the elements inside the collection in any
order, thus types that conform to `MutableCollectionType` can represent
collections with a domain-specific element order (not every instance of a
`MutableCollectionType` has an interesting order, though).

Range Replaceable Collections
-----------------------------

The `MutableCollectionType` protocol implies only mutation of content, not of
structure (for example, changing the number of elements).  The
`RangeReplaceableCollectionType` protocol adds the capability to perform
structural mutation, which in its most general form is expressed as replacing a
range of elements, denoted by two indices, by elements from a collection with a
**different** length.

::

  public protocol RangeReplaceableCollectionType : MutableCollectionType {
    mutating func replaceSubrange<
      C: CollectionType where C.Iterator.Element == Self.Iterator.Element
    >(
      _ subRange: Range<Index>, with newElements: C
    )
  }


Index Protocols
---------------

As a generalization designed to cover diverse data structures,
`CollectionType` provides weaker guarantees than arrays do.  In
particular, an arbitrary collection does not necessarily offer
efficient random access; that property is determined by the protocol
conformances of its `Index` type.

**Forward indices** are the simplest and most general, capturing the
capabilities of indices into a singly-linked list:

1. advance to the next position
2. detect the end position

**Bidirectional indices** are a refinement of forward indices that
additionally support reverse traversal::

  protocol BidirectionalIndexType : ForwardIndexType {
    func predecessor() -> Self
  }

Indices into a doubly-linked list would be bidirectional, as are the
indices that address `Character`\ s and `UnicodeScalar`\ s in a
`String`.  Reversing the order of a collection's elements is a simple
example of a generic algorithm that depends on bidirectional traversal.

**Random access indices** have two more requirements: the ability to
efficiently measure the number of steps between arbitrary indices
addressing the same collection, and the ability to advance an index by
a (possibly negative) number of steps::

  public protocol RandomAccessIndexType : BidirectionalIndexType {
    func distance(to other: Self) -> Distance
    func advanced(by n: Distance) -> Self
  }

From these methods, the standard library derives several other
features such as `Comparable` conformance, index subtraction, and
addition/subtraction of integers to/from indices.

The indices of a `deque
<https://en.wikipedia.org/wiki/Double-ended_queue>`_ can provide random
access, as do the indices into `String.UTF16View` (when Foundation is
loaded) and, of course, array indices.  Many common sorting and
selection algorithms, among others, depend on these capabilities.

All direct operations on indices are intended to be lightweight, with
amortized O(1) complexity.  In fact, indices into `Dictionary` and
`Set` *could* be bidirectional, but are limited to modeling
`ForwardIndexType` because the APIs of `NSDictionary` and
`NSSet`—which can act as backing stores of `Dictionary` and `Set`—do
not efficiently support reverse traversal.

Conclusion
==========

Swift's sequence, collection, and index protocols allow us to write
general algorithms that apply to a wide variety of series and data
structures.  The system has been both easy to extend, and predictably
performant.  Thanks for taking the tour!

------

.. [#input_iterator] This trade-off is not as obvious as it might
   seem.  For example, the C# and C++ analogues for `IteratorProtocol`
   (`IEnumerable` and `input iterator`) are saddled with the
   obligation to provide buffering.
