'lazy' 的使用不明确

Ambiguous use of 'lazy'

我不知道为什么 this example 是模棱两可的。 (我很抱歉没有在这里添加代码,它太长了。)

我已将 prefix (_ maxLength) 作为重载添加到 LazyDropWhileBidirectionalCollectionsubscript(position) 是在 LazyPrefixCollection 上定义的。然而,上面示例中的以下代码不应该有歧义,但它是:

print([0, 1, 2].lazy.drop(while: {_ in false}).prefix(2)[0]) // Ambiguous use of 'lazy'

据我了解,将使用协议层次结构中更高层的重载。

根据编译器,它不能在两种类型之间进行选择;即 LazyRandomAccessCollectionLazySequence。 (这没有意义,因为 subscript(position) 不是 LazySequence 的方法。)LazyRandomAccessCollection 是这里合乎逻辑的选择。

如果我删除下标,它会起作用:

print(Array([0, 1, 2].lazy.drop(while: {_ in false}).prefix(2))) // [0, 1]

可能是什么问题?

将最后一行更改为:

let x = [0, 1, 2]

let lazyX:  LazySequence                = x.lazy
let lazyX2: LazyRandomAccessCollection  = x.lazy
let lazyX3: LazyBidirectionalCollection = x.lazy
let lazyX4: LazyCollection              = x.lazy

print(lazyX.drop(while: {_ in false}).prefix(2)[0])

您会注意到数组有 4 种不同的惰性构造 - 您必须明确。

这里的踪迹太过复杂和模糊。您可以通过删除元素来查看。特别是去掉最后一个下标:

let z = [0, 1, 2].lazy.drop(while: {_ in false}).prefix(2)

在此配置中,编译器希望将 z 键入为 LazyPrefixCollection<LazyDropWhileBidirectionalCollection<[Int]>>。但这不能用整数索引。 我知道它应该是这样,但当前的编译器无法证明它。(见下文)所以你的 [0] 失败了。而且回溯还不够强大,无法退出这个疯狂的迷宫。不同 return 类型的重载太多了,编译器不知道你想要哪一种。

但是这个特殊情况很容易修复:

print([0, 1, 2].lazy.drop(while: {_ in false}).prefix(2).first!)

就是说,我绝对会避免这么用力地推动编译器。这对今天的 Swift 来说太聪明了。特别是 return 不同类型的重载在 Swift 中通常不是一个好主意。当它们很简单时,是的,你可以摆脱它。但是当你开始对它们进行分层时,编译器没有足够强大的证明引擎来解决它。 (也就是说,如果我们研究了足够长的时间,我敢打赌它实际上在某种程度上是模棱两可的,但诊断具有误导性。当你变得过于聪明时,这是一种非常常见的情况 Swift。)


既然你描述了它(在评论中),推理就很简单了。

LazyDropWhileCollection 不能有整数索引。索引下标必须是 O(1)。这就是 Index 下标与其他下标的含义。 (Index 下标还必须 return Element 类型,否则会崩溃;它不能 return 和 Element?。这就是 DictionaryIndexKey 不同。)

由于集合是惰性的并且有任意数量的缺失元素,查找任何特定整数 "count"(第一个、第二个等)是 O(n)。如果不遍历至少 100 个元素,就不可能知道第 100 个元素是什么。要成为一个集合,它的 O(1) 索引必须采用一种只能通过先前遍历序列来创建的形式。不能是 Int.

这很重要,因为当您编写如下代码时:

for i in 1...1000 { print(xs[i]) }

你希望它是 1000 的数量级 "steps," 但如果这个集合有一个整数索引,它将是 100 万步的数量级。通过包装索引,它们可以防止您首先编写该代码。

这在像 Swift 这样的高度通用语言中尤其重要,在这种语言中,通用算法层可以轻松地将意外的 O(n) 操作级联成完全不可行的性能("unworkable" 我的意思是您预计需要花费几分钟或更长时间的毫秒数。