> Le 15 avr. 2016 à 17:59, Brent Royal-Gordon via swift-evolution
> <[email protected]> a écrit :
>
> 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 see this purely as a documentation issue. It should clearly state the number
is not to be used to subscript into the array. Even 'indices' likely warrant a
warning that it is pointless to use in some construct such as:
for i in array.filter({ $0 % 2 == 0 }).indices { print("\(i) is not to index
array") }
Which of course can be safely be written as
for i in array.indices where array[i] % 2 == 0 { print("\(i) can be used as
subscript") }
If we want to have a way to safely subscript into the original array for all
possible use cases, we may need a way to "dictionarize" the array.
Providing a new 'enumerated()' which returns the proper array subscript for the
simple case where the array is not post-processed (with filter for example)
could lead to a false sense of safety when using such construct as subscript
into the array.
Dany
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution