If I make two generators and call next() on both, nothing strange happens:

let generator = wrapper.generate()

let another = wrapper.generate()

generator.next() // 1

another.next() // 1

So far, so good. However, if I first call dropFirst() on my wrapper, I get strange behaviour:

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?

If I use dropLast() instead of dropFirst(), the outputs are 1 and 1, as expected.

If I don't use the wrapper struct I made, but a direct AnySequence instance instead, nothing out of the ordinary happens:

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

I can't make any sense of this. What's going on here?

网友答案:

You would have to debug through the behavior to understand the specific behavior, but this most likely happens because SequenceType is not required to be iterable multiple times.

SequenceType makes no requirement on conforming types regarding
whether they will be destructively "consumed" by iteration. To ensure
non-destructive iteration, constrain your sequence to CollectionType.

As a consequence, it is not possible to run multiple for loops on a sequence to "resume" iteration:

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 makes no requirement about the behavior in that case. It
is not correct to assume that a sequence will either be "consumable"
and will resume iteration, or that a sequence is a collection and will
restart iteration from the first element. A conforming sequence that
is not a collection is allowed to produce an arbitrary sequence of
elements from the second generator.

In other words, the two generators that you get from calling generate() twice are not guaranteed to not interfere with one another. In fact, it's legal for a type to implement both SequenceType and GeneratorType and implement generate() as return self. Any shared state (from member references, or if the sequence itself is a reference type) will be shared across generators, which is why you should only make one.

网友答案:

The internal dropFirst() method returns a new instance of AnySequence (as you can see in this line: https://github.com/apple/swift/blob/master/stdlib/public/core/Sequence.swift#l1070).