[swift-evolution] [Idea] Replace enumerate() with something more explicit

Andrew Bennett cacoyi at gmail.com
Fri Apr 15 20:09:45 CDT 2016


I'm in support of a method of getting a sequence of (Index,Value) pairs (as
you know from the other thread). I think I'm leaning toward option three if
it's equivalent to `zip(self.indices, self)`, ideally as a concise property
like keys/values on a Dictionary.

I've been using zip in production. I presumed enumerate was intended for
enumerating indices, and that it had just been forgotten when the slice
changes went through. I'm in favour of removing it.


On Sat, Apr 16, 2016 at 7:59 AM, Brent Royal-Gordon via swift-evolution <
swift-evolution at swift.org> wrote:

> A discussion in the "mapValues" thread reminded me of a longstanding issue
> I have with Swift.
>
> `enumerate()` is an attractive nuisance. (That is, it looks like the thing
> you want, but it's not actually the right one.) Most people use it because
> they want to enumerate over indices and elements at the same time. In
> reality, though, the first element of an `enumerate()` tuple is not the
> index—it's a monotonically increasing integer starting at 0. That *happens*
> to work for `Array`:
>
> >         1>     let array = Array(0..<10)
> >         2.     for (i, elem) in array.enumerate() {
> >         3.         print(array[i])
> >         4.     }
> >       0
> >       1
> >       2
> >       3
> >       4
> >       5
> >       6
> >       7
> >       8
> >       9
>
> But if you stray even a little bit from the golden path, things start to
> go wrong:
>
> >         5>     let range = array[2..<8]
> >         6.     for (i, elem) in range.enumerate() {
> >         7.         print(range[i])
> >         8.     }
> >       fatal error: Index out of bounds
>
> You can scarcely blame users for making this mistake, though—"The Swift
> Programming Language" encourages the misconception. "Iterating Over an
> Array" in "Collection Types":
>
> > If you need the integer index of each item as well as its value, use the
> `enumerate()` method to iterate over the array instead. For each item in
> the array, the `enumerate()` method returns a tuple composed of the index
> and the value for that item.
>
>
> While the text is technically accurate—it only talks about iterating over
> arrays and the numbers generated by `enumerate()` happen to correspond to
> array indices—it creates a false implication that `enumerate()` is defined
> to return indices, which isn't true of other collections.
>
> This is made worse by the fact that `enumerate()` is not really a good
> name. It is not a common word, so people don't read it and immediately
> understand what it does; they memorize a Swift-specific meaning, and that
> meaning may incorporate the misconception that `enumerate()` includes
> indices. It is also not technically accurate: although it has "number" in
> its Latin roots, "enumerate" means either "to count" or "to list", not "to
> number" (i.e. assign numbers to). I know `enumerate()` is used in a couple
> of other languages (certainly Python, possibly others), but I don't think
> that overrides the fact that it's confusing.
>
> I have three possible solutions to propose.
>
>
>
> OPTION ONE
>
> * Remove `enumerate()`.
>
> * Provide a type and postfix operator which allows you to write an
> infinite sequence as `0...`. (This might call a ClosedRange constructor
> which constrains the type to a protocol which provides `max`. This would
> imply that `FloatingPoint` and `Integer` protocols would need to conform to
> a common protocol declaring a `max` property, and in the case of
> `FloatingPoint`, `max` should probably be positive infinity.)
>
> * Fix-It calls to `x.enumerate()` as `zip(0..., x)`. This is more
> complicated to look at, but it's *far* more explicit about what the
> operation actually does. (For bonus points, we could perhaps look at how
> the EnumerateSequence is used, and if the number is used as an index, go
> with `zip(x.indices, x)` instead.)
>
>
>
> OPTION TWO
>
> * Rename `enumerate()` to something more explicit, like `withIntegers()`
> or `numbered()`. (It might even make sense to add a `from:` parameter which
> defaults to 0.)
>
> * Add to Collection an equivalent method with a similar name that provides
> indices, like `withIndices()` or `indexed()`.
>
> * Fix-It calls to `enumerate()` into either `numbered()` or `indexed()`
> (or whatever they end up being called) depending on the way they are used.
>
>
>
> OPTION THREE
>
> Combine the other two options:
>
> * Provide the infinite numeric sequence type from Option One.
>
> * Provide `numbered()` and `indexed()` (or whatever) methods which are
> explicitly typed to merely zip over the sequence/collection with an
> infinite integer sequence/Indices collection.
>
> --
> Brent Royal-Gordon
> Architechies
>
> _______________________________________________
> 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/20160416/3bf2985d/attachment.html>


More information about the swift-evolution mailing list