我有一个包装序列的包装器:
struct SequenceWrapper<T>: SequenceType {
var sequence: AnySequence<T>
func generate() -> AnyGenerator<T> {
return sequence.generate()
}
}
let wrapper = SequenceWrapper(sequence: AnySequence(1 ... 10))
如果我制作两个生成器并在两者上调用next()
,则不会发生任何奇怪的事情:
let generator = wrapper.generate()
let another = wrapper.generate()
generator.next() // 1
another.next() // 1
到目前为止,这么好。但是,如果我首先在我的包装器上调用dropFirst()
,我会遇到奇怪的行为:
let wrapper = SequenceWrapper(sequence: AnySequence(1 ... 10))
let trimmed = wrapper.dropFirst()
let generator = trimmed.generate()
let another = trimmed.generate()
generator.next() // 2
another.next() // 3, huh?
如果我使用dropLast()
代替dropFirst()
,则输出为1
和1
,如预期的那样。
如果我不使用我制作的包装struct
,而是使用直接AnySequence
实例,则不会发生任何异常情况:
let sequence = AnySequence(1 ... 10)
let trimmed = sequence.dropFirst()
let generator = trimmed.generate()
let another = trimmed.generate()
generator.next() // 2
another.next() // 2, as expected
我无法理解这一点。这里发生了什么?
答案 0 :(得分:2)
您必须通过行为进行调试才能了解具体行为,但最有可能的原因是SequenceType
为not required to be iterable multiple times。
SequenceType
对要求的符合类型没有要求 他们是否会破坏性地消费&#34;通过迭代。确保 非破坏性迭代,将您的序列约束为CollectionType
。因此,不可能在序列上运行多个for循环来恢复&#34;迭代:
for element in sequence { if ... some condition { break } } for element in sequence { // Not guaranteed to continue from the next element. // [mine: not guaranteed to restart from the beginning either] }
SequenceType
对此案例中的行为没有要求。它 假设一个序列是&#34;消耗品&#34;是不正确的。 并将恢复迭代,或序列是一个集合,并将 从第一个元素重新开始迭代。一致的序列 不是一个集合是允许产生任意序列的 来自第二个发电机的元件。
换句话说,您从调用generate()
两次获得的两个生成器不能保证不会相互干扰。事实上,实现SequenceType
和GeneratorType
并将generate()
实现为return self
的类型是合法的。任何共享状态(来自成员引用,或者如果序列本身是引用类型)将在生成器之间共享,这就是为什么你应该只创建一个。
答案 1 :(得分:0)
内部dropFirst()
方法返回AnySequence的新实例(正如您在此行中所见:https://github.com/apple/swift/blob/master/stdlib/public/core/Sequence.swift#l1070)。
您需要添加到SequenceWrapper
的内容是以下几行:
func dropFirst() -> SequenceWrapper.SubSequence {
return sequence.dropFirst()
}
以下是用于测试的简短Playground代码段:
struct SequenceWrapper<T>: SequenceType {
var sequence: AnySequence<T>
func generate() -> AnyGenerator<T> {
return sequence.generate()
}
func dropFirst() -> SequenceWrapper.SubSequence {
return sequence.dropFirst()
}
}
let wrapper = SequenceWrapper(sequence: AnySequence(1 ... 10))
var generator = wrapper.generate()
var another = wrapper.generate()
generator.next() // 1
another.next() // 1
var trimmed = wrapper.dropFirst()
generator = trimmed.generate()
another = trimmed.generate()
generator.next() // 2
another.next() // 2! :)