+1 looks good, I had a go at implementing it and I think it may require changes not discussed in the proposal.
You've covered the potential issues fairly well, to be a little more explicit these are the issues I've found: 1) LazySequenceType's property array cannot be defined without an infinite sized array. 2) what should [1,2,3].cycle.suffix(4) return? [3,1,2,3] probably has the least surprises, but it's like asking what's the number before infinity. 3) dropLast should return AnySequence(self), but requires specialisation, this may have to also be a fatalError (see below). One issue I don't think you've mentioned, and I don't seem to be able to resolve is this: let mySequence = [1,2,3].cycle.dropLast(1) mySequence.suffix(7) This could have well defined behaviour (see part 2 above), however the implementation has some issues. In this case mySequence is an AnySequence<Int>, mySequence.suffix(7) uses AnySequence's specialisation and so tries to iterate over the entire sequence to find the suffix. AnySequence<Int> is type-erased so there's no way to specialise when the underlying sequence is infinite (to get a valid implementation of suffix). Potential solutions: * Replace erased Any* types with a more flexible alternative that doesn't remove type information (higher kinded types perhaps). * Replace SequenceType with two protocols FiniteSequenceType and InfiniteSequenceType, have type erased versions of each, duplicate all the things. * Add a property to SequenceType to indicate if it's definitely finite (undefined?), AnySequence uses a different backing implementation depending on this boolean. Here's the implementation I used in a playground to toy with this: public struct CycleSequence<Base : CollectionType> : LazySequenceType { private let base: Base private init(_ collection: Base) { self.base = collection } @warn_unused_result public func generate() -> CycleGenerator<Base> { return CycleGenerator<Base>(base.generate) } public var array: [Base.Generator.Element] { fatalError("This is undefined!") } } public struct CycleGenerator<Base : CollectionType> : GeneratorType { private let generatorProducer: () -> Base.Generator private var generator: Base.Generator private init(_ generatorProducer: () -> Base.Generator) { self.generatorProducer = generatorProducer self.generator = generatorProducer() } @warn_unused_result public mutating func next() -> Base.Generator.Element? { if let element = generator.next() { return element } generator = generatorProducer() return generator.next() } } extension CycleSequence { @warn_unused_result public func dropLast(n: Int) -> AnySequence<Base.Generator.Element> { return AnySequence(self) } @warn_unused_result public func suffix(maxLength: Int) -> AnySequence<Base.Generator.Element> { let maxCount = base.count.toIntMax() let sequenceLength = maxCount >= Int.max.toIntMax() ? Int.max : Int (maxCount) if maxLength < sequenceLength { return AnySequence(base.suffix(maxLength)) } return self.dropFirst(sequenceLength - (maxLength % sequenceLength)).prefix(maxLength) } } extension CollectionType { public var cycle: CycleSequence<Self> { return CycleSequence(self) } } // this produces an infinite loop when evaluating .suffix(7) let cycle = ["a", "b", "c"].cycle cycle.dropLast(1).suffix(7).forEach { print("suffix: \($0)") } On Mon, Dec 28, 2015 at 6:35 PM, Developer via swift-evolution < swift-evolution@swift.org> wrote: > +1. Stream support is long overdue. > > ~Robert Widmann > > 2015/12/28 2:20、Kevin Ballard via swift-evolution < > swift-evolution@swift.org> のメッセージ: > > > ## Introduction > > > > Add a new property `cycle` to CollectionType that returns an infinite > SequenceType that yields the elements of the collection in a loop. > > > > ## Motivation > > > > It's sometimes useful to be able to have an infinite sequence. For > example, `CollectionOfOne(x).cycle` could be used to have an infinite > sequence of a single element (similar to Repeat but without a count). A > common use for infinite sequences is zipping with a finite sequence. As far > as I'm aware, the stdlib does not currently provide any way to create such > an infinite sequence. > > > > ## Proposed solution > > > > Extend CollectionType with a new property `cycle` that yields a type > that conforms to SequenceType. This sequence yields each element of the > collection in an infinite loop. > > > > ## Detailed design > > > > 2 new types would be added: > > > > struct CycleSequence<Base : CollectionType> : LazySequenceType { ... } > > struct CycleGenerator<Base : CollectionType> : GeneratorType { ... } > > > > CollectionType would be extended with a property: > > > > extension CollectionType { > > public var cycle: CycleSequence<Self> { get } > > } > > > > This is an extension of CollectionType instead of SequenceType because > it requires a multi-pass sequence (and SequenceType does not provide that > guarantee). The returned type conforms to SequenceType instead of > CollectionType because there is no possible `endIndex` that satisfies the > requirement of being reachable from `startIndex` by zero or more > applications of `successor()`. > > > > Because the default eager versions of map and filter will execute > forever on an infinite sequence, CycleSequence conforms to LazySequenceType > instead of SequenceType in order to provide lazy versions of those > functions. Additionally, it will provide implementations of the eager > versions that simply trigger a fatalError(), as the alternative is an > infinite loop that consumes more and more memory. > > > > ## Impact on existing code > > > > None > > > > -Kevin Ballard > > _______________________________________________ > > swift-evolution mailing list > > swift-evolution@swift.org > > https://lists.swift.org/mailman/listinfo/swift-evolution > _______________________________________________ > swift-evolution mailing list > swift-evolution@swift.org > https://lists.swift.org/mailman/listinfo/swift-evolution >
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution