[swift-evolution] [Proposal draft] Introducing `indexed()` collections

Dave Abrahams dabrahams at apple.com
Fri Sep 30 22:53:32 CDT 2016


on Wed Sep 28 2016, Erica Sadun <swift-evolution at swift.org> wrote:

> Indices have a specific, fixed meaning in Swift, which are used to create valid collection
> subscripts. This proposal introduces indexed() to produce a more semantically relevant sequence by
> pairing a collection's indices with its members. While it is trivial to create a solution in Swift,
> the most common developer approach shown here calculates indexes twice:
>
> extension Collection {
>     /// Returns a sequence of pairs (*idx*, *x*), where *idx* represents a
>     /// consecutive collection index, and *x* represents an element of
>     /// the sequence.
>     func indexed() -> Zip2Sequence<Self.Indices, Self> {
>         return zip(indices, self)
>     }
> }

How does this calculate indices twice?

> Incrementing an index in some collections can be unnecessarily
> costly. 

Seems like it's only *unnecessarily* costly in badly implemented
collections?

> In a lazy filtered collection, an index increment is potentially
> O(N). We feel this is better addressed introducing a new function into
> the Standard Library to provide a more efficient design that avoids
> the attractive nuisance of the "obvious" solution.

I am generally opposed to adding this.  The usual solution developers
will reach for here is:

    for i in x.indices {
        somethingWith(x[i])
    }

zip(indices, self) is only suboptimal for lazy filtered sequences, which
should be used with care anyhow (see the note here:
http://swiftdoc.org/v3.0/type/LazyFilterCollection/).

If you really need a lazy sequence of pairs that's optimal with lazy
filtered sequences, 

    x.indices.lazy.map { ($0, x[$0]) }

is a good solution and pretty easy to write.

-- 
-Dave



More information about the swift-evolution mailing list