[swift-evolution] [Idea] Add an (Index, Element) sequence to CollectionType

Kevin Ballard kevin at sb.org
Mon Dec 28 00:06:10 CST 2015


What you're asking for can already be done with `zip(col.indices, col)`.
And in my experience the need for this sort of thing is rare enough that
there's no need to have a dedicated property for it in the stdlib. The
few times that I've needed this sort of thing, I've always just said

for index in col.indices {    let elt = col[index]    // ... }

and that's pretty simple. But if I ever did need to map it, I'd just use
the aforementioned zip() expression.

-Kevin Ballard

On Sun, Dec 27, 2015, at 12:08 AM, Patrick Pijnappel via swift-evolution wrote:
> -- Introduction
>
> There should be a property on CollectionType that returns a sequence
> of (Index, Element) tuples. Currently enumerate() is often used
> instead, but it is not well suited to the task and can lead to bugs.
>
>
>
> -- Motivation
>
> Using enumerate() instead of an (Index, Element) sequence has two main
> problems. Both arise because enumerate() returns a sequence of (n,
> Element) tuples, where n is the element *number*, instead of a
> sequence of (Index, Element).
>
> 1) It doesn't work for collections not indexed by integers.
>
> 2) It doesn't do what you might expect in some cases, as indices do
>    not always start at 0. For example ArraySlice's indices do not:
>    array[2..<5] starts with index 2. Consider the following code to
>    take the 2nd half of the array and remove all empty elements:
>
> var array = [ "", "a", "b", "c", "", "d" ] var secondHalf =
> array[array.count/2..<array.count] for (index, element) in
> secondHalf.enumerate() { if element == "" {
> secondHalf.removeAtIndex(index) } }
>
> This code will crash (ignoring for a moment this should probably be
> using filter).
>
>
>
> -- Alternatives
>
> The same effect can already be achieved using the following:
>
> for index in collection.indices {  let element = collection[index]
> // ... }
>
> However having a dedicated (Index, Element) sequence has the following
> advantages:
> a) It can help prevent people from using enumerate() inappropriately.
> b) It is very common use case that deserves shortening.
> c) It can be chained (e.g. to map).
>
>
>
> -- Proposed Solution
>
> Add a property/method on CollectionType that returns a sequence of
> (Index, Element) tuples. For example, using a property named indexed:
>
> for (index, element) in collection.indexed {  // ... }
>
> This should be the preferred idiom when you want both the index and
> the element.
>
> Note that enumerate() does still have valid roles to play:
> - When you actually do want the element number, not the index.
> - When you have a SequenceType, as it isn't indexed.
>
>
>
> -- Implementation
>
> The feature could be entirely implemented using existing constructs:
>
> extension CollectionType {  var indexed: AnySequence<(Index,
> Generator.Element)> {    return AnySequence(indices.lazy.map { ($0,
> self[$0]) })  } }
>
> Alternatively, a dedicated SequenceType and/or GeneratorType could
> be added.
>
>
> _________________________________________________
> swift-evolution mailing list swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20151227/45e6f544/attachment.html>


More information about the swift-evolution mailing list