gpt4 book ai didi

swift - 'lazy' 的使用不明确

转载 作者:行者123 更新时间:2023-11-28 06:12:06 24 4
gpt4 key购买 nike

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

我添加了 prefix (_ maxLength) 作为 LazyDropWhileBidirectionalCollection 的重载。 subscript(position)LazyPrefixCollection 上定义。然而,上面示例中的以下代码不应该是模棱两可的,但它确实是:

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

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

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

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

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

可能是什么问题?

最佳答案

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

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

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

但这个特殊情况是微不足道的固定:

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

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


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

LazyDropWhileCollection不能有整数索引。索引下标必须是 O(1)。这就是 Index 的意思下标与其他下标。 (Index 下标还必须返回 Element 类型,否则会崩溃;它不能返回 Element? 。这就是 DictionaryIndexKey 分开的方式。)

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

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

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

您希望它大约为 1000 个“步骤”,但如果此集合有一个整数索引,它将大约为 100 万个步骤。通过包装索引,它们可以防止您首先编写该代码。

这在像 Swift 这样的高度通用的语言中尤为重要,在 Swift 中,通用算法层可以轻松地将意外的 O(n) 操作级联成完全不可行的性能(我所说的“不可行”是指你期望花费几毫秒的事情需要几分钟或更多)。

关于swift - 'lazy' 的使用不明确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46257248/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com