Swift lazy subscript ignores filter

戏子无情 提交于 2020-07-08 06:14:07

问题


How does subscripting a lazy filter work?

let ary = [0,1,2,3]
let empty = ary.lazy.filter { $0 > 4 }.map { $0 + 1 }
print(Array(empty)) // []
print(empty[2])     // 3

It looks like it just ignores the filter and does the map anyway. Is this documented somewhere? What other lazy collections have exceptional behavior like this?


回答1:


It comes down to subscripting a LazyFilterCollection with an integer which in this case ignores the predicate and forwards the subscript operation to the base.

For example, if we're looking for the strictly positive integers in an array :

let array = [-10, 10, 20, 30]
let lazyFilter = array.lazy.filter { $0 > 0 }

print(lazyFilter[3])                 // 30

Or, if we're looking for the lowercase characters in a string :

let str = "Hello"
let lazyFilter = str.lazy.filter { $0 > "Z" }

print(lazyFilter[str.startIndex])    //H

In both cases, the subscript is forwarded to the base collection.

The proper way of subscripting a LazyFilterCollection is using a LazyFilterCollection<Base>.Index as described in the documentation :

let start = lazyFilter.startIndex
let index = lazyFilter.index(start, offsetBy: 1)
print(lazyFilter[index])  

Which yields 20 for the array example, or l for the string example.


In your case, trying to access the index 3:

let start = empty.startIndex
let index = empty.index(start, offsetBy: 3)
print(empty)

would raise the expected runtime error :

Fatal error: Index out of range




回答2:


To add to Carpsen90's answer, you run into one of Collection's particularities: it's not recommended, nor safe to access collections by an absolute index, even if the type system allows this. Because the collection you receive might be a subset of another one.

Let's take a simpler example, array slicing:

let array = [0, 1, 2, 3, 4]
let slice = array[2..<3]
print(slice) // [2]
print(slice.first) // Optional(2)
print(slice[0]) // crashes with array index out of bounds

Even if slice is a collection indexable by an integer, it's still unsafe to use absolute integers to access elements of that collection, as the collection might have a different set of indices.



来源:https://stackoverflow.com/questions/54294501/swift-lazy-subscript-ignores-filter

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!