diff --git a/stdlib/public/core/ExistentialCollection.swift.gyb b/stdlib/public/core/ExistentialCollection.swift.gyb index f637f67083500..07fb35cc60d3a 100644 --- a/stdlib/public/core/ExistentialCollection.swift.gyb +++ b/stdlib/public/core/ExistentialCollection.swift.gyb @@ -224,7 +224,14 @@ public struct AnySequence : SequenceType { public typealias T = Element /// Wrap and forward operations to `base`. - public init(_ base: S) { + public init< + S: SequenceType + where + S.Generator.Element == Element, + S.SubSequence : SequenceType, + S.SubSequence.Generator.Element == Element, + S.SubSequence.SubSequence == S.SubSequence + >(_ base: S) { _box = _SequenceBox(base) } diff --git a/stdlib/public/core/Sequence.swift b/stdlib/public/core/Sequence.swift index dca54b1d35bf0..75b629b8bad7c 100644 --- a/stdlib/public/core/Sequence.swift +++ b/stdlib/public/core/Sequence.swift @@ -331,63 +331,6 @@ extension SequenceType { return Array(result) } - /// Returns a subsequence containing all but the first `n` elements. - /// - /// - Requires: `n >= 0` - /// - Complexity: O(`n`) - @warn_unused_result - public func dropFirst(n: Int) -> AnySequence { - _precondition(n >= 0, "Can't drop a negative number of elements from a sequence") - if n == 0 { return AnySequence(self) } - // If this is already a _DropFirstSequence, we need to fold in - // the current drop count and drop limit so no data is lost. - // - // i.e. [1,2,3,4].dropFirst(1).dropFirst(1) should be equivalent to - // [1,2,3,4].dropFirst(2). - // FIXME: Use method dispatch to fold - // _PrefixSequence and _DropFirstSequence counts - if let any = self as? AnySequence, - let box = any._box as? _SequenceBox<_DropFirstSequence> { - let base = box._base - let folded = _DropFirstSequence(base.generator, limit: base.limit + n, - dropped: base.dropped) - return AnySequence(folded) - } - - return AnySequence(_DropFirstSequence(generate(), limit: n)) - } - - /// Returns a subsequence containing all but the last `n` elements. - /// - /// - Requires: `self` is a finite collection. - /// - Requires: `n >= 0` - /// - Complexity: O(`self.count`) - @warn_unused_result - public func dropLast(n: Int) -> AnySequence { - _precondition(n >= 0, "Can't drop a negative number of elements from a sequence") - if n == 0 { return AnySequence(self) } - // FIXME: Create reusable RingBuffer - // Put incoming elements from this sequence in a holding tank, a ring buffer - // of size <= n. If more elements keep coming in, pull them out of the - // holding tank into the result, an `Array`. This saves - // `n` * sizeof(Generator.Element) of memory, because slices keep the entire - // memory of an `Array` alive. - var result: [Generator.Element] = [] - var ringBuffer: [Generator.Element] = [] - var i = ringBuffer.startIndex - - for element in self { - if ringBuffer.count < n { - ringBuffer.append(element) - } else { - result.append(ringBuffer[i]) - ringBuffer[i] = element - i = i.successor() % n - } - } - return AnySequence(result) - } - @warn_unused_result public func prefix(maxLength: Int) -> AnySequence { _precondition(maxLength >= 0, "Can't take a prefix of negative length from a sequence") @@ -526,9 +469,7 @@ extension SequenceType { ) -> Bool? { return nil } -} -extension SequenceType { /// Call `body` on each element in `self` in the same order as a /// *for-in loop.* /// @@ -585,6 +526,69 @@ extension SequenceType where Generator.Element : Equatable { } } +extension SequenceType where + SubSequence : SequenceType, + SubSequence.Generator.Element == Generator.Element, + SubSequence.SubSequence == SubSequence { + + /// Returns a subsequence containing all but the first `n` elements. + /// + /// - Requires: `n >= 0` + /// - Complexity: O(`n`) + @warn_unused_result + public func dropFirst(n: Int) -> AnySequence { + _precondition(n >= 0, "Can't drop a negative number of elements from a sequence") + if n == 0 { return AnySequence(self) } + // If this is already a _DropFirstSequence, we need to fold in + // the current drop count and drop limit so no data is lost. + // + // i.e. [1,2,3,4].dropFirst(1).dropFirst(1) should be equivalent to + // [1,2,3,4].dropFirst(2). + // FIXME: Use method dispatch to fold + // _PrefixSequence and _DropFirstSequence counts + if let any = self as? AnySequence, + let box = any._box as? _SequenceBox<_DropFirstSequence> { + let base = box._base + let folded = _DropFirstSequence(base.generator, limit: base.limit + n, + dropped: base.dropped) + return AnySequence(folded) + } + + return AnySequence(_DropFirstSequence(generate(), limit: n)) + } + + /// Returns a subsequence containing all but the last `n` elements. + /// + /// - Requires: `self` is a finite collection. + /// - Requires: `n >= 0` + /// - Complexity: O(`self.count`) + @warn_unused_result + public func dropLast(n: Int) -> AnySequence { + _precondition(n >= 0, "Can't drop a negative number of elements from a sequence") + if n == 0 { return AnySequence(self) } + // FIXME: Create reusable RingBuffer + // Put incoming elements from this sequence in a holding tank, a ring buffer + // of size <= n. If more elements keep coming in, pull them out of the + // holding tank into the result, an `Array`. This saves + // `n` * sizeof(Generator.Element) of memory, because slices keep the entire + // memory of an `Array` alive. + var result: [Generator.Element] = [] + var ringBuffer: [Generator.Element] = [] + var i = ringBuffer.startIndex + + for element in self { + if ringBuffer.count < n { + ringBuffer.append(element) + } else { + result.append(ringBuffer[i]) + ringBuffer[i] = element + i = i.successor() % n + } + } + return AnySequence(result) + } +} + extension SequenceType { /// Returns a subsequence containing all but the first element. ///