Swift 惰性下标忽略过滤器
Swift lazy subscript ignores filter
订阅延迟过滤器如何工作?
let ary = [0,1,2,3]
let empty = ary.lazy.filter { [=11=] > 4 }.map { [=11=] + 1 }
print(Array(empty)) // []
print(empty[2]) // 3
看起来它只是忽略了过滤器并无论如何都做了地图。这在某处记录了吗?还有哪些惰性集合有这样的异常行为?
归结为用整数下标 LazyFilterCollection
,在这种情况下忽略谓词并将下标操作转发给基数。
例如,如果我们要查找数组中的严格正整数:
let array = [-10, 10, 20, 30]
let lazyFilter = array.lazy.filter { [=10=] > 0 }
print(lazyFilter[3]) // 30
或者,如果我们要查找字符串中的小写字符:
let str = "Hello"
let lazyFilter = str.lazy.filter { [=11=] > "Z" }
print(lazyFilter[str.startIndex]) //H
在这两种情况下,下标都被转发到基础集合。
下标 LazyFilterCollection
的正确方法是使用 LazyFilterCollection<Base>.Index
,如 documentation 中所述:
let start = lazyFilter.startIndex
let index = lazyFilter.index(start, offsetBy: 1)
print(lazyFilter[index])
数组示例生成 20
,字符串示例生成 l
。
在您的情况下,尝试访问索引 3
:
let start = empty.startIndex
let index = empty.index(start, offsetBy: 3)
print(empty)
会引发预期的运行时错误:
Fatal error: Index out of range
为了补充 Carpsen90 的回答,您 运行 进入了 Collection
的一个特殊性:不推荐,也不安全地通过绝对索引访问 collections,即使类型系统允许这样做。因为您收到的 collection 可能是另一个的子集。
举个更简单的例子,数组切片:
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
即使 slice
是一个可由整数索引的 collection,使用绝对整数访问 collection 的元素仍然是不安全的,因为 collection 可能有一组不同的指数。
订阅延迟过滤器如何工作?
let ary = [0,1,2,3]
let empty = ary.lazy.filter { [=11=] > 4 }.map { [=11=] + 1 }
print(Array(empty)) // []
print(empty[2]) // 3
看起来它只是忽略了过滤器并无论如何都做了地图。这在某处记录了吗?还有哪些惰性集合有这样的异常行为?
归结为用整数下标 LazyFilterCollection
,在这种情况下忽略谓词并将下标操作转发给基数。
例如,如果我们要查找数组中的严格正整数:
let array = [-10, 10, 20, 30]
let lazyFilter = array.lazy.filter { [=10=] > 0 }
print(lazyFilter[3]) // 30
或者,如果我们要查找字符串中的小写字符:
let str = "Hello"
let lazyFilter = str.lazy.filter { [=11=] > "Z" }
print(lazyFilter[str.startIndex]) //H
在这两种情况下,下标都被转发到基础集合。
下标 LazyFilterCollection
的正确方法是使用 LazyFilterCollection<Base>.Index
,如 documentation 中所述:
let start = lazyFilter.startIndex
let index = lazyFilter.index(start, offsetBy: 1)
print(lazyFilter[index])
数组示例生成 20
,字符串示例生成 l
。
在您的情况下,尝试访问索引 3
:
let start = empty.startIndex
let index = empty.index(start, offsetBy: 3)
print(empty)
会引发预期的运行时错误:
Fatal error: Index out of range
为了补充 Carpsen90 的回答,您 运行 进入了 Collection
的一个特殊性:不推荐,也不安全地通过绝对索引访问 collections,即使类型系统允许这样做。因为您收到的 collection 可能是另一个的子集。
举个更简单的例子,数组切片:
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
即使 slice
是一个可由整数索引的 collection,使用绝对整数访问 collection 的元素仍然是不安全的,因为 collection 可能有一组不同的指数。