> 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

Reply via email to