//===--- DropWhile.swift.gyb - Lazy views for drop(while:) ----*- swift -*-===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// %{ from gyb_stdlib_support import ( TRAVERSALS, collectionForTraversal ) }% //===--- Iterator & Sequence ----------------------------------------------===// /// An iterator over the elements traversed by a base iterator that follow the /// initial consecutive elements that satisfy a given predicate. /// /// This is the associated iterator for the `LazyDropWhileSequence`, /// `LazyDropWhileCollection`, and `LazyDropWhileBidirectionalCollection` /// types. public struct LazyDropWhileIterator : IteratorProtocol, Sequence { public mutating func next() -> Base.Element? { // Once the predicate has failed for the first time, the base iterator // can be used for the rest of the elements. if _predicateHasFailed { return _base.next() } // Retrieve and discard elements from the base iterator until one fails // the predicate. while let nextElement = _base.next() { if !_predicate(nextElement) { _predicateHasFailed = true return nextElement } } return nil } internal init(_base: Base, predicate: @escaping (Base.Element) -> Bool) { self._base = _base self._predicate = predicate } internal var _predicateHasFailed = false internal var _base: Base internal let _predicate: (Base.Element) -> Bool } /// A sequence whose elements consist of the elements that follow the initial /// consecutive elements of some base sequence that satisfy a given predicate. public struct LazyDropWhileSequence : LazySequenceProtocol { public typealias Elements = LazyDropWhileSequence /// Returns an iterator over the elements of this sequence. /// /// - Complexity: O(1). public func makeIterator() -> LazyDropWhileIterator { return LazyDropWhileIterator( _base: _base.makeIterator(), predicate: _predicate) } /// Create an instance with elements `transform(x)` for each element /// `x` of base. internal init(_base: Base, predicate: @escaping (Base.Iterator.Element) -> Bool) { self._base = _base self._predicate = predicate } internal var _base: Base internal let _predicate: (Base.Iterator.Element) -> Bool } extension LazySequenceProtocol { /// Returns a lazy sequence that skips any initial elements that satisfy /// `predicate`. /// /// - Parameter predicate: A closure that takes an element of the sequence as /// its argument and returns `true` if the element should be skipped or /// `false` otherwise. Once `predicate` returns `false` it will not be /// called again. public func drop( while predicate: @escaping (Elements.Iterator.Element) -> Bool ) -> LazyDropWhileSequence { return LazyDropWhileSequence(_base: self.elements, predicate: predicate) } } //===--- Collections ------------------------------------------------------===// /// A position in a `LazyDropWhileCollection` or /// `LazyDropWhileBidirectionalCollection` instance. public struct LazyDropWhileIndex : Comparable { /// The position corresponding to `self` in the underlying collection. public let base: Base.Index } public func == ( lhs: LazyDropWhileIndex, rhs: LazyDropWhileIndex ) -> Bool { return lhs.base == rhs.base } public func < ( lhs: LazyDropWhileIndex, rhs: LazyDropWhileIndex ) -> Bool { return lhs.base < rhs.base } % for Traversal in ['Forward', 'Bidirectional']: % Collection = collectionForTraversal(Traversal) % Self = "LazyDropWhile" + Collection /// A lazy `${Collection}` wrapper that includes the elements of an underlying /// collection after any initial consecutive elements that satisfy a /// predicate. /// /// - Note: The performance of accessing `startIndex`, `first`, or any methods /// that depend on `startIndex` depends on how many elements satisfy the /// predicate at the start of the collection, and may not offer the usual /// performance given by the `Collection` protocol. Be aware, therefore, /// that general operations on `${Self}` instances may not have the /// documented complexity. public struct ${Self}< Base : ${Collection} > : LazyCollectionProtocol, ${Collection} { // FIXME(compiler limitation): should be inferable. public typealias Index = LazyDropWhileIndex public var startIndex: Index { var index = _base.startIndex while index != _base.endIndex && _predicate(_base[index]) { _base.formIndex(after: &index) } return LazyDropWhileIndex(base: index) } public var endIndex: Index { return LazyDropWhileIndex(base: _base.endIndex) } public func index(after i: Index) -> Index { _precondition(i.base < _base.endIndex, "can't advance past endIndex") return LazyDropWhileIndex(base: _base.index(after: i.base)) } % if Traversal == 'Bidirectional': public func index(before i: Index) -> Index { _precondition(i > startIndex, "can't move before startIndex") return LazyDropWhileIndex(base: _base.index(before: i.base)) } % end public subscript(position: Index) -> Base.Iterator.Element { return _base[position.base] } public func makeIterator() -> LazyDropWhileIterator { return LazyDropWhileIterator( _base: _base.makeIterator(), predicate: _predicate) } internal init(_base: Base, predicate: @escaping (Base.Iterator.Element) -> Bool) { self._base = _base self._predicate = predicate } internal var _base: Base internal let _predicate: (Base.Iterator.Element) -> Bool } extension LazyCollectionProtocol where Self : ${Collection}, Elements : ${Collection} { /// Returns a lazy collection that skips any initial elements that satisfy /// `predicate`. /// /// - Parameter predicate: A closure that takes an element of the collection /// as its argument and returns `true` if the element should be skipped or /// `false` otherwise. Once `predicate` returns `false` it will not be /// called again. public func drop( while predicate: @escaping (Elements.Iterator.Element) -> Bool ) -> LazyDropWhile${Collection} { return LazyDropWhile${Collection}( _base: self.elements, predicate: predicate) } } % end // ${'Local Variables'}: // eval: (read-only-mode 1) // End: