Skip to content

Instantly share code, notes, and snippets.

@erica
Last active July 11, 2016 15:54
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save erica/4db99d721547e8113e2fce30e0418613 to your computer and use it in GitHub Desktop.
Save erica/4db99d721547e8113e2fce30e0418613 to your computer and use it in GitHub Desktop.
/// A buffered sequence that contains all the elements of
/// a source sequence, with a one-element lookahead buffer
public struct BufferedSequence<BaseSequence : Sequence>: IteratorProtocol, Sequence {
internal var _base: BaseSequence
internal var _iterator: BaseSequence.Iterator
internal var bufferedElement: BaseSequence.Iterator.Element?
public init(_ base: BaseSequence) {
_base = base
_iterator = base.makeIterator()
bufferedElement = _iterator.next()
}
public mutating func next() -> BaseSequence.Iterator.Element? {
defer { bufferedElement = _iterator.next() ?? nil }
return bufferedElement
}
}
extension Sequence {
/// Returns a subsequence containing the initial elements until `predicate`
/// returns `false`, skipping all remaining elements
public func prefix(while predicate: (Self.Iterator.Element) -> Bool) -> AnyIterator<Self.Iterator.Element> {
var iterator = self.makeIterator()
return AnyIterator {
return iterator.next().flatMap({ return predicate($0) ? $0 : nil })
}
}
/// Returns a subsequence containing the initial elements until `predicate`
/// returns `false`, skipping all remaining elements
public func drop(while predicate: (Self.Iterator.Element) -> Bool) -> AnyIterator<Self.Iterator.Element> {
var bufferedSequence = BufferedSequence(self)
while let element = bufferedSequence.bufferedElement where predicate(element) {
let _ = bufferedSequence.next() // drop
}
return AnyIterator(bufferedSequence)
}
}
/// Returns a sequence formed from `first` and repeated lazy applications of
/// `next` until `predicate` is false.
///
/// The first element in the sequence is always `first`, and each successive
/// element is the result of invoking `next` with the previous element. The
/// sequence ends when `next` returns `nil`. If `next` never returns `nil`, the
/// sequence is infinite.
///
/// - Parameter first: The first element to be returned from the sequence.
/// - Parameter next: A closure that accepts the previous sequence element and
/// returns the next element.
/// - Parameter while: A closure that accepts the previous sequence element and
/// returns true or false, indicating whether the sequence should continue.
/// - Returns: A sequence that starts with `first` and continues with every
/// value returned by passing the previous element to `next` until the
/// predicate
///
/// - SeeAlso: `sequence(state:next:)`, `sequence(first:next:)`
public func sequence<T>(first: T, next: (T) -> T?, while endTest: (T) -> Bool) -> AnyIterator<T> {
return sequence(first: first, next: next).prefix(while: endTest)
}
// For example: prints 0...12 by 2s
//for i in sequence(first: 0, next: { $0 + 2 }, while: { $0 < 14 }) {
// print(i)
//}
// For example: prints: 10...18 by 2s
let s = sequence(first: 0, next: { $0 + 2 }, while: { $0 < 20 })
for teenValue in s.drop(while: { $0 < 10 }) {
print(teenValue)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment