Swift 当我尝试提供我自己的 AnySequence 实现时无法推断泛型类型
Swift couldn't infer generic type when I was trying to provide my own implementation of AnySequence
问题是当一个协议通过其关联类型依赖于另一个协议时,编译器无法推断泛型类型。
所以,我正在研究 Swift 的类型擦除技术,试图熟悉它的想法。在我使用 Sequence 协议之前,基本上它是可以理解的。众所周知,它有一个关联类型 - Iterator,它符合 IteratorProtocol。也就是说,我一直在尝试在我自己的实现中实现类似的行为。这就是我所做的:
final class CustomAnySequence<Element>: Sequence {
class CustomAnyIterator<Element>: IteratorProtocol {
private let _next: () -> Element?
init<I: IteratorProtocol>(_ iterator: I) where I.Element == Element {
var iterator = iterator
_next = { iterator.next() }
}
func next() -> Element? {
return _next()
}
}
typealias Iterator = CustomAnyIterator<Element>
typealias Element = Iterator.Element
private let _makeIterator: () -> Iterator
init<S: Sequence>(_ sequence: S) where S.Iterator == Iterator {
_makeIterator = sequence.makeIterator
}
func makeIterator() -> Iterator {
return _makeIterator()
}
}
let sequence = CustomAnySequence([1, 2, 3])
所以,最后一行给出了以下错误:无法推断通用参数'Element'。
然后,如果我尝试通过明确指定元素类型来修复它:
let sequence = CustomAnySequence<Int>([1, 2, 3])
它并没有让它变得更好。下一个 Xcode 投诉是:无法推断通用参数 'S'。
那是我的错,还是 Swift 的类型推断的开销太大了?
实际上,我已经 运行 进入另一个可能的实现 - 它使用私有子类包装。我不太喜欢它(这就是我尝试自己做的原因),因为在超类的实现中有 "fatal-error-must-be-subclassed" 方法,这些方法无助于清洁代码。此外,我不确定如何通过 CustomAnySequence 的初始化程序实现此功能(我只发现它可以通过制作静态方法实现)。尽管如此,这就是代码:
class CustomAnySequence<Element>: Sequence {
class Iterator: IteratorProtocol {
func next() -> Element? {
fatalError("Must be overriden")
}
}
func makeIterator() -> Iterator {
fatalError("Must be overriden")
}
}
private final class CustomAnySequenceImplementation<S: Sequence>: CustomAnySequence<S.Element> {
final class IteratorImplementation: Iterator {
var wrapped: S.Iterator
init(_ wrapped: S.Iterator) {
self.wrapped = wrapped
}
override func next() -> S.Element? {
return wrapped.next()
}
}
var sequence: S
init(_ sequence: S) {
self.sequence = sequence
}
override func makeIterator() -> IteratorImplementation {
return IteratorImplementation(sequence.makeIterator())
}
}
extension CustomAnySequence {
static func make<S: Sequence>(_ sequence: S) -> CustomAnySequence<Element> where S.Element == Element {
return CustomAnySequenceImplementation<S>(sequence)
}
}
func printInts(_ sequence: CustomAnySequence<Int>) {
for element in sequence {
print(element)
}
}
printInts(CustomAnySequence.make([1, 2, 3]))
printInts(CustomAnySequence.make(Set([4, 5, 6])))
它实际上确实有效,但它看起来有点像样板。 至少,如果您知道如何使用初始化器改进它,请告诉我。提前致谢!
第一个实现的问题是
let sequence = CustomAnySequence([1, 2, 3])
不满足
中的约束
init<S: Sequence>(_ sequence: S) where S.Iterator == Iterator
[1, 2, 3]
是一个序列,但是它的迭代器类型不是你的CustomAnyIterator
。您真正想要的是传递具有相同 element 类型而不是相同迭代器类型的序列:
init<S: Sequence>(_ sequence: S) where S.Element == Element
并将sequence.makeIterator()
传递给CustomAnyIterator
的初始化方法。
另请注意,内部 class 可以从外部 class 继承 Element
类型占位符,并且实际上不需要类型别名。
final class CustomAnySequence<Element>: Sequence {
class CustomAnyIterator: IteratorProtocol {
private let _next: () -> Element?
init<I: IteratorProtocol>(_ iterator: I) where I.Element == Element {
var iterator = iterator
_next = { iterator.next() }
}
func next() -> Element? {
return _next()
}
}
private let _makeIterator: () -> CustomAnyIterator
init<S: Sequence>(_ sequence: S) where S.Element == Element {
_makeIterator = { CustomAnyIterator(sequence.makeIterator()) }
}
func makeIterator() -> CustomAnyIterator {
return _makeIterator()
}
}
您也可以考虑使用 struct
而不是 class
。
问题是当一个协议通过其关联类型依赖于另一个协议时,编译器无法推断泛型类型。
所以,我正在研究 Swift 的类型擦除技术,试图熟悉它的想法。在我使用 Sequence 协议之前,基本上它是可以理解的。众所周知,它有一个关联类型 - Iterator,它符合 IteratorProtocol。也就是说,我一直在尝试在我自己的实现中实现类似的行为。这就是我所做的:
final class CustomAnySequence<Element>: Sequence {
class CustomAnyIterator<Element>: IteratorProtocol {
private let _next: () -> Element?
init<I: IteratorProtocol>(_ iterator: I) where I.Element == Element {
var iterator = iterator
_next = { iterator.next() }
}
func next() -> Element? {
return _next()
}
}
typealias Iterator = CustomAnyIterator<Element>
typealias Element = Iterator.Element
private let _makeIterator: () -> Iterator
init<S: Sequence>(_ sequence: S) where S.Iterator == Iterator {
_makeIterator = sequence.makeIterator
}
func makeIterator() -> Iterator {
return _makeIterator()
}
}
let sequence = CustomAnySequence([1, 2, 3])
所以,最后一行给出了以下错误:无法推断通用参数'Element'。
然后,如果我尝试通过明确指定元素类型来修复它:
let sequence = CustomAnySequence<Int>([1, 2, 3])
它并没有让它变得更好。下一个 Xcode 投诉是:无法推断通用参数 'S'。
那是我的错,还是 Swift 的类型推断的开销太大了?
实际上,我已经 运行 进入另一个可能的实现 - 它使用私有子类包装。我不太喜欢它(这就是我尝试自己做的原因),因为在超类的实现中有 "fatal-error-must-be-subclassed" 方法,这些方法无助于清洁代码。此外,我不确定如何通过 CustomAnySequence 的初始化程序实现此功能(我只发现它可以通过制作静态方法实现)。尽管如此,这就是代码:
class CustomAnySequence<Element>: Sequence {
class Iterator: IteratorProtocol {
func next() -> Element? {
fatalError("Must be overriden")
}
}
func makeIterator() -> Iterator {
fatalError("Must be overriden")
}
}
private final class CustomAnySequenceImplementation<S: Sequence>: CustomAnySequence<S.Element> {
final class IteratorImplementation: Iterator {
var wrapped: S.Iterator
init(_ wrapped: S.Iterator) {
self.wrapped = wrapped
}
override func next() -> S.Element? {
return wrapped.next()
}
}
var sequence: S
init(_ sequence: S) {
self.sequence = sequence
}
override func makeIterator() -> IteratorImplementation {
return IteratorImplementation(sequence.makeIterator())
}
}
extension CustomAnySequence {
static func make<S: Sequence>(_ sequence: S) -> CustomAnySequence<Element> where S.Element == Element {
return CustomAnySequenceImplementation<S>(sequence)
}
}
func printInts(_ sequence: CustomAnySequence<Int>) {
for element in sequence {
print(element)
}
}
printInts(CustomAnySequence.make([1, 2, 3]))
printInts(CustomAnySequence.make(Set([4, 5, 6])))
它实际上确实有效,但它看起来有点像样板。 至少,如果您知道如何使用初始化器改进它,请告诉我。提前致谢!
第一个实现的问题是
let sequence = CustomAnySequence([1, 2, 3])
不满足
中的约束init<S: Sequence>(_ sequence: S) where S.Iterator == Iterator
[1, 2, 3]
是一个序列,但是它的迭代器类型不是你的CustomAnyIterator
。您真正想要的是传递具有相同 element 类型而不是相同迭代器类型的序列:
init<S: Sequence>(_ sequence: S) where S.Element == Element
并将sequence.makeIterator()
传递给CustomAnyIterator
的初始化方法。
另请注意,内部 class 可以从外部 class 继承 Element
类型占位符,并且实际上不需要类型别名。
final class CustomAnySequence<Element>: Sequence {
class CustomAnyIterator: IteratorProtocol {
private let _next: () -> Element?
init<I: IteratorProtocol>(_ iterator: I) where I.Element == Element {
var iterator = iterator
_next = { iterator.next() }
}
func next() -> Element? {
return _next()
}
}
private let _makeIterator: () -> CustomAnyIterator
init<S: Sequence>(_ sequence: S) where S.Element == Element {
_makeIterator = { CustomAnyIterator(sequence.makeIterator()) }
}
func makeIterator() -> CustomAnyIterator {
return _makeIterator()
}
}
您也可以考虑使用 struct
而不是 class
。