为什么 indexingIterator.next() 使用动态调度?
Why is indexingIterator.next() using dynamic dispatch?
我写了这个。
感谢那些回答我的人,我本可以学到 Seqeunce
和 IteratorProtocol
.
所以我实现了符合 Sequence
的自定义类型(School
下面的代码)。
我检查了 Xcode 时间配置文件。
但我找不到任何东西协议见证
但是如果只使用 range
和 for-in
,时间分析器显示 protocol witness.
为什么 indexingIterator.next()
使用 动态方法 而不是 School
?
我以为即使struct
符合protocol
,如果struct
类型的变量使用protocol
的方法,这个方法就会是静态方法 .如果我错了,你能告诉我错在哪里吗?
⬇️School
代码
struct SchoolIterator: IteratorProtocol {
private var schoolList: School
var idx = 0
init(_ school: School) {
self.schoolList = school
}
mutating func next() -> String? {
defer { idx += 1 }
guard schoolList.count-1 >= idx
else { return nil }
return schoolList[idx]
}
}
struct School: Sequence {
fileprivate var list = Array(repeating: "school", count: 100000)
var count: Int { return list.count }
subscript(_ idx: Int ) -> String? {
guard idx <= count-1
else { return nil }
return list[idx]
}
func makeIterator() -> SchoolIterator {
return SchoolIterator(self)
}
}
var schools = School()
for school in schools {
print(school)
}
您的 for 循环转换为:
var schools = School()
var iterator = schools.makeIterator()
while let school = iterator.next() {
print(school)
}
注意这里什么都不是协议。 schools
是 School
类型,iterator
是 SchoolIterator
类型,next
所做的一切(比如访问 schoolList.count
,或 schoolList.count
的下标=20=]) 也处理结构。关键是编译器可以准确地弄清楚你指的是哪个成员,因为它的(编译时)类型是一个结构。无需查找 witness tables.
将其与
进行比较
func f<S: Sequence>(_ s: S) {
for thing in s {
...
}
/*
var iterator: S.Iterator = s.makeIterator()
while let thing = iterator.next() {
...
}
*/
}
f(School())
f(1..<100)
编译器如何将调用分派给 iterator.next()
?我特意添加了类型注释以明确发生了什么——这一次,编译器不知道你指的是哪个 next
。是IndexingIterator.next()
吗?还是SchoolIterator.next()
?还是SomeOtherIterator.next()
?请记住,我可以用任何类型的 Sequence
调用 f
!这就是为什么它需要在运行时 查找 S.Iterator
实际类型的见证 table - 不可能找出 next
到哪个 next
打电话。
至于为什么for i in 0..<100
使用动态调度,嗯,乍一看,似乎所有的结构:
let range: Range<Int> = 0..<100
var iterator: IndexingIterator<Range<Int>> = range.makeIterator()
while let i = iterator.next() {
...
}
然而,iterator.next
实际上做了类似 this 的事情:
public 变异函数 next() -> Elements.Element? {
如果 _position == _elements.endIndex { return 无 }
让元素 = _elements[_position]
_elements.formIndex(之后:&_position)
return 元素
}
_elements
定义如下:
public struct IndexingIterator<Elements: Collection> {
internal let _elements: Elements
_elements
可以是任何类型的 Collection
,所以同样,我们不知道在编译时 _elements[_position]
或 _elements.formIndex
指的是哪个成员。是Array.formIndex
吗?还是Set.formIndex
?我们只在运行时知道,当我们知道 Elements
是什么时。
推荐阅读:https://medium.com/@venki0119/method-dispatch-in-swift-effects-of-it-on-performance-b5f120e497d3
Seqeunce
和 IteratorProtocol
.
所以我实现了符合 Sequence
的自定义类型(School
下面的代码)。
我检查了 Xcode 时间配置文件。
但我找不到任何东西协议见证
但是如果只使用 range
和 for-in
,时间分析器显示 protocol witness.
为什么 indexingIterator.next()
使用 动态方法 而不是 School
?
我以为即使struct
符合protocol
,如果struct
类型的变量使用protocol
的方法,这个方法就会是静态方法 .如果我错了,你能告诉我错在哪里吗?
⬇️School
代码
struct SchoolIterator: IteratorProtocol {
private var schoolList: School
var idx = 0
init(_ school: School) {
self.schoolList = school
}
mutating func next() -> String? {
defer { idx += 1 }
guard schoolList.count-1 >= idx
else { return nil }
return schoolList[idx]
}
}
struct School: Sequence {
fileprivate var list = Array(repeating: "school", count: 100000)
var count: Int { return list.count }
subscript(_ idx: Int ) -> String? {
guard idx <= count-1
else { return nil }
return list[idx]
}
func makeIterator() -> SchoolIterator {
return SchoolIterator(self)
}
}
var schools = School()
for school in schools {
print(school)
}
您的 for 循环转换为:
var schools = School()
var iterator = schools.makeIterator()
while let school = iterator.next() {
print(school)
}
注意这里什么都不是协议。 schools
是 School
类型,iterator
是 SchoolIterator
类型,next
所做的一切(比如访问 schoolList.count
,或 schoolList.count
的下标=20=]) 也处理结构。关键是编译器可以准确地弄清楚你指的是哪个成员,因为它的(编译时)类型是一个结构。无需查找 witness tables.
将其与
进行比较func f<S: Sequence>(_ s: S) {
for thing in s {
...
}
/*
var iterator: S.Iterator = s.makeIterator()
while let thing = iterator.next() {
...
}
*/
}
f(School())
f(1..<100)
编译器如何将调用分派给 iterator.next()
?我特意添加了类型注释以明确发生了什么——这一次,编译器不知道你指的是哪个 next
。是IndexingIterator.next()
吗?还是SchoolIterator.next()
?还是SomeOtherIterator.next()
?请记住,我可以用任何类型的 Sequence
调用 f
!这就是为什么它需要在运行时 查找 S.Iterator
实际类型的见证 table - 不可能找出 next
到哪个 next
打电话。
至于为什么for i in 0..<100
使用动态调度,嗯,乍一看,似乎所有的结构:
let range: Range<Int> = 0..<100
var iterator: IndexingIterator<Range<Int>> = range.makeIterator()
while let i = iterator.next() {
...
}
然而,iterator.next
实际上做了类似 this 的事情:
public 变异函数 next() -> Elements.Element? { 如果 _position == _elements.endIndex { return 无 } 让元素 = _elements[_position] _elements.formIndex(之后:&_position) return 元素 }
_elements
定义如下:
public struct IndexingIterator<Elements: Collection> {
internal let _elements: Elements
_elements
可以是任何类型的 Collection
,所以同样,我们不知道在编译时 _elements[_position]
或 _elements.formIndex
指的是哪个成员。是Array.formIndex
吗?还是Set.formIndex
?我们只在运行时知道,当我们知道 Elements
是什么时。
推荐阅读:https://medium.com/@venki0119/method-dispatch-in-swift-effects-of-it-on-performance-b5f120e497d3