Skip to content

[stdlib][WIP perf experiment] Replace AnySequence with Array in default Sequence methods #9639

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions stdlib/public/core/DropFirst.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
//===-- DropFirst.swift ---------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 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
//
//===----------------------------------------------------------------------===//

/// A sequence that lazily consumes and drops `n` elements from an underlying
/// `Base` iterator before possibly returning the first available element.
///
/// The underlying iterator's sequence may be infinite.
///
/// This is a class - we require reference semantics to keep track
/// of how many elements we've already dropped from the underlying sequence.
@_versioned
@_fixed_layout
public class _DropFirstSequence<Base : IteratorProtocol>
: Sequence, IteratorProtocol {

@_versioned
internal var _iterator: Base
@_versioned
internal let _limit: Int
@_versioned
internal var _dropped: Int

@_versioned
@_inlineable
internal init(_iterator: Base, limit: Int, dropped: Int = 0) {
self._iterator = _iterator
self._limit = limit
self._dropped = dropped
}

@_versioned
@_inlineable
internal func makeIterator() -> _DropFirstSequence<Base> {
return self
}

@_versioned
@_inlineable
internal func next() -> Base.Element? {
while _dropped < _limit {
if _iterator.next() == nil {
_dropped = _limit
return nil
}
_dropped += 1
}
return _iterator.next()
}

@_versioned
@_inlineable
internal func dropFirst(_ n: Int) -> AnySequence<Base.Element> {
// 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).
return AnySequence(
_DropFirstSequence(
_iterator: _iterator, limit: _limit + n, dropped: _dropped))
}
}
76 changes: 76 additions & 0 deletions stdlib/public/core/DropWhile.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
//===-- DropWhile.swift ---------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 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
//
//===----------------------------------------------------------------------===//

/// A sequence that lazily consumes and drops `n` elements from an underlying
/// `Base` iterator before possibly returning the first available element.
///
/// The underlying iterator's sequence may be infinite.
///
/// This is a class - we require reference semantics to keep track
/// of how many elements we've already dropped from the underlying sequence.
@_fixed_layout
@_versioned
public class _DropWhileSequence<Base : IteratorProtocol>
: Sequence, IteratorProtocol {

typealias Element = Base.Element

@_versioned
internal var _iterator: Base
@_versioned
internal var _nextElement: Base.Element?

@_versioned
@_inlineable
internal init(
iterator: Base,
nextElement: Base.Element?,
predicate: (Base.Element) throws -> Bool
) rethrows {
self._iterator = iterator
self._nextElement = nextElement ?? _iterator.next()

while try _nextElement.flatMap(predicate) == true {
_nextElement = _iterator.next()
}
}

@_versioned
@_inlineable
internal func makeIterator() -> _DropWhileSequence<Base> {
return self
}

@_versioned
@_inlineable
internal func next() -> Element? {
guard _nextElement != nil else {
return _iterator.next()
}

let next = _nextElement
_nextElement = nil
return next
}

@_versioned
@_inlineable
internal func drop(
while predicate: (Element) throws -> Bool
) rethrows -> AnySequence<Element> {
// If this is already a _DropWhileSequence, avoid multiple
// layers of wrapping and keep the same iterator.
return try AnySequence(
_DropWhileSequence(
iterator: _iterator, nextElement: _nextElement, predicate: predicate))
}
}
68 changes: 68 additions & 0 deletions stdlib/public/core/Prefix.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
//===-- Prefix.swift ------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 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
//
//===----------------------------------------------------------------------===//

/// A sequence that lazily consumes up to `n` elements from an underlying
/// `Base` iterator.
///
/// The underlying iterator's sequence may be infinite.
///
/// This is a class - we require reference semantics to keep track
/// of how many elements we've already taken from the underlying sequence.
@_fixed_layout
@_versioned
public class _PrefixSequence<Base : IteratorProtocol>
: Sequence, IteratorProtocol {
@_versioned
internal let _maxLength: Int
@_versioned
internal var _iterator: Base
@_versioned
internal var _taken: Int

@_versioned
@_inlineable
internal init(_iterator: Base, maxLength: Int, taken: Int = 0) {
self._iterator = _iterator
self._maxLength = maxLength
self._taken = taken
}

@_versioned
@_inlineable
internal func makeIterator() -> _PrefixSequence<Base> {
return self
}

@_versioned
@_inlineable
internal func next() -> Base.Element? {
if _taken >= _maxLength { return nil }
_taken += 1

if let next = _iterator.next() {
return next
}

_taken = _maxLength
return nil
}

@_versioned
@_inlineable
internal func prefix(_ maxLength: Int) -> AnySequence<Base.Element> {
return AnySequence(
_PrefixSequence(
_iterator: _iterator,
maxLength: Swift.min(maxLength, self._maxLength),
taken: _taken))
}
}
Loading