我有一个包装序列的包装器:

struct SequenceWrapper<T>: SequenceType {
    var sequence: AnySequence<T>

    func generate() -> AnyGenerator<T> {
        return sequence.generate()
    }
}

let wrapper = SequenceWrapper(sequence: AnySequence(1 ... 10))

如果我生成两个生成器并同时调用这两个生成器,则不会发生任何奇怪的情况:
let generator = wrapper.generate()
let another = wrapper.generate()

generator.next() // 1
another.next()   // 1

到目前为止,一切都很好。但是,如果我第一次在包装上调用next()
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?

如果我使用dropFirst()而不是dropLast(),输出结果如预期一样为dropFirst()1
如果我不使用我制作的包装器,而是直接使用一个1实例,则不会发生任何异常情况:
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

我听不懂。这是怎么回事?

最佳答案

为了理解特定的行为,您必须调试整个行为,但这很可能是因为SequenceTypenot required to be iterable multiple times
SequenceType不要求符合以下类型:
它们是否会被迭代破坏性地“消耗”。确保
非破坏性迭代,将序列约束为CollectionType
因此,不可能在序列上运行多个for循环来“恢复”迭代:

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对这种情况下的行为没有任何要求。它
假设一个序列要么是“可消耗的”,这是不正确的。
将恢复迭代,或者序列是集合,并且将
从第一个元素重新开始迭代。一个一致的序列
不允许集合生成
来自第二个生成器的元素。
换言之,您两次调用generate()得到的两个生成器不能保证互相干扰。实际上,一个类型同时实现SequenceTypeGeneratorType和将generate()实现为return self是合法的。任何共享状态(来自成员引用,或者序列本身是引用类型)都将在生成器之间共享,这就是为什么您应该只创建一个共享状态的原因。

10-08 06:24