提问人:3366784 提问时间:11/23/2020 最后编辑:3366784 更新时间:11/24/2020 访问量:137
当 Self 实现 IteratorProtocol 时,Swift 如何推断 Sequence 需求?
How does Swift infer Sequence requirements when Self implements IteratorProtocol?
问:
我正在阅读 Sequence 文档,并在他们使用的示例(见下文)中推断出 Sequence 的要求。我的问题是它是如何推断的。我了解推理在更简单的情况下是如何工作的,但在这个例子中,我无法理解 Swift 是如何推断事物的。
我看到 Sequence 的 makeIterator 方法有一个默认实现,但我不明白这里是如何推断返回值的。
例
struct Countdown: Sequence, IteratorProtocol {
var count: Int
mutating func next() -> Int? {
if count == 0 {
return nil
} else {
defer { count -= 1 }
return count
}
}
}
上述类型的参考
IteratorProtocol {
func next() -> Self.Element?
associatedtype Iterator
associatedtype Element
}
Sequence {
func makeIterator() -> Self.Iterator
associatedtype Iterator
associatedtype Element
}
答:
让我们从 的实现开始。编译器看到以下实现:IteratorProtocol.next
mutating func next() -> Int? {
if count == 0 {
return nil
} else {
defer { count -= 1 }
return count
}
}
并注意到它返回一个 .那么,IteratorProtocol.next
应该返回一个 ,所以它推断 .现在满足.Int?
Self.Element?
IteratorProtocol.Element == Int
Coundown
IteratorProtocol
请注意,并共享关联的类型。一旦 Swift 找出了 的见证人,就好像你在 中声明了一个新的类型别名,而恰好需要它存在。Sequence
IteratorProtocol
Element
IteratorProtcol.Element
Element
Countdown
Sequence
Countdown.Element
之后,编译器推断 .这样一来,默认实现 是可用的。然而,编译器如何推断这一点是一个谜,因为只有这些信息,通常无法推断类型,这可以通过创建自己的序列和迭代器协议来证明。Iterator == Self
makeIterator
protocol MyIterator {
associatedtype Element
mutating func next() -> Element?
}
protocol MySequence {
associatedtype Element where Element == Iterator.Element
associatedtype Iterator : MyIterator
func makeIterator() -> Iterator
}
extension MySequence where Self == Self.Iterator {
func makeIterator() -> Iterator {
return self
}
}
struct Countdown: MySequence, MyIterator { // doesn't compile
var count: Int
mutating func next() -> Int? {
if count == 0 {
return nil
} else {
defer { count -= 1 }
return count
}
}
}
在查看了源代码之后,我怀疑可能会有一些编译器的魔力,尤其是这里:
// Provides a default associated type witness for Iterator when the
// Self type is both a Sequence and an Iterator.
extension Sequence where Self: IteratorProtocol {
// @_implements(Sequence, Iterator)
public typealias _Default_Iterator = Self
}
这似乎设置了一个“首选”类型,以便推断为。它似乎在说“当不能推断为任何东西时,请尝试”。我在其他任何地方都找不到,这就是为什么我得出结论,这是编译器的魔力。这样做的全部目的是让您通过仅遵守和实现 来遵守,正如文档所说的那样。Iterator
Iterator
Self
_Default_Iterator
Sequence
IteratorProtocol
next
现在,我们也满足了以下条件的约束:Iterator == Self
Element
associatedtype Element where Self.Element == Self.Iterator.Element
因此,我们已经证明符合 。Countdown
Sequence
评论
Sequence