//===--- Map.swift - Lazily map over a Sequence ---------------*- 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` whose elements consist of those in a `Base` /// `Sequence` passed through a transform function returning `Element`. /// These elements are computed lazily, each time they're read, by /// calling the transform function on a base element. @_fixed_layout public struct LazyMapSequence { public typealias Elements = LazyMapSequence @usableFromInline internal var _base: Base @usableFromInline internal let _transform: (Base.Element) -> Element /// Creates an instance with elements `transform(x)` for each element /// `x` of base. @inlinable internal init(_base: Base, transform: @escaping (Base.Element) -> Element) { self._base = _base self._transform = transform } } extension LazyMapSequence { @_fixed_layout public struct Iterator { @usableFromInline internal var _base: Base.Iterator @usableFromInline internal let _transform: (Base.Element) -> Element @inlinable public var base: Base.Iterator { return _base } @inlinable internal init( _base: Base.Iterator, _transform: @escaping (Base.Element) -> Element ) { self._base = _base self._transform = _transform } } } extension LazyMapSequence.Iterator: IteratorProtocol, Sequence { /// Advances to the next element and returns it, or `nil` if no next element /// exists. /// /// Once `nil` has been returned, all subsequent calls return `nil`. /// /// - Precondition: `next()` has not been applied to a copy of `self` /// since the copy was made. @inlinable public mutating func next() -> Element? { return _base.next().map(_transform) } } extension LazyMapSequence: LazySequenceProtocol { /// Returns an iterator over the elements of this sequence. /// /// - Complexity: O(1). @inlinable public func makeIterator() -> Iterator { return Iterator(_base: _base.makeIterator(), _transform: _transform) } /// A value less than or equal to the number of elements in the sequence, /// calculated nondestructively. /// /// The default implementation returns 0. If you provide your own /// implementation, make sure to compute the value nondestructively. /// /// - Complexity: O(1), except if the sequence also conforms to `Collection`. /// In this case, see the documentation of `Collection.underestimatedCount`. @inlinable public var underestimatedCount: Int { return _base.underestimatedCount } } /// A `Collection` whose elements consist of those in a `Base` /// `Collection` passed through a transform function returning `Element`. /// These elements are computed lazily, each time they're read, by /// calling the transform function on a base element. @_fixed_layout public struct LazyMapCollection { @usableFromInline internal var _base: Base @usableFromInline internal let _transform: (Base.Element) -> Element /// Create an instance with elements `transform(x)` for each element /// `x` of base. @inlinable internal init(_base: Base, transform: @escaping (Base.Element) -> Element) { self._base = _base self._transform = transform } } extension LazyMapCollection: Sequence { public typealias Iterator = LazyMapSequence.Iterator /// Returns an iterator over the elements of this sequence. /// /// - Complexity: O(1). @inlinable public func makeIterator() -> Iterator { return Iterator(_base: _base.makeIterator(), _transform: _transform) } /// A value less than or equal to the number of elements in the sequence, /// calculated nondestructively. /// /// - Complexity: O(1) if the collection conforms to /// `RandomAccessCollection`; otherwise, O(*n*), where *n* is the length /// of the collection. @inlinable public var underestimatedCount: Int { return _base.underestimatedCount } } extension LazyMapCollection: LazyCollectionProtocol { public typealias Index = Base.Index public typealias Indices = Base.Indices public typealias SubSequence = LazyMapCollection @inlinable public var startIndex: Base.Index { return _base.startIndex } @inlinable public var endIndex: Base.Index { return _base.endIndex } @inlinable public func index(after i: Index) -> Index { return _base.index(after: i) } @inlinable public func formIndex(after i: inout Index) { _base.formIndex(after: &i) } /// Accesses the element at `position`. /// /// - Precondition: `position` is a valid position in `self` and /// `position != endIndex`. @inlinable public subscript(position: Base.Index) -> Element { return _transform(_base[position]) } @inlinable public subscript(bounds: Range) -> SubSequence { return SubSequence(_base: _base[bounds], transform: _transform) } @inlinable public var indices: Indices { return _base.indices } /// A Boolean value indicating whether the collection is empty. @inlinable public var isEmpty: Bool { return _base.isEmpty } /// The number of elements in the collection. /// /// To check whether the collection is empty, use its `isEmpty` property /// instead of comparing `count` to zero. Unless the collection guarantees /// random-access performance, calculating `count` can be an O(*n*) /// operation. /// /// - Complexity: O(1) if `Index` conforms to `RandomAccessIndex`; O(*n*) /// otherwise. @inlinable public var count: Int { return _base.count } @inlinable public var first: Element? { return _base.first.map(_transform) } @inlinable public func index(_ i: Index, offsetBy n: Int) -> Index { return _base.index(i, offsetBy: n) } @inlinable public func index( _ i: Index, offsetBy n: Int, limitedBy limit: Index ) -> Index? { return _base.index(i, offsetBy: n, limitedBy: limit) } @inlinable public func distance(from start: Index, to end: Index) -> Int { return _base.distance(from: start, to: end) } } extension LazyMapCollection : BidirectionalCollection where Base : BidirectionalCollection { /// A value less than or equal to the number of elements in the collection. /// /// - Complexity: O(1) if the collection conforms to /// `RandomAccessCollection`; otherwise, O(*n*), where *n* is the length /// of the collection. @inlinable public func index(before i: Index) -> Index { return _base.index(before: i) } @inlinable public func formIndex(before i: inout Index) { _base.formIndex(before: &i) } @inlinable public var last: Element? { return _base.last.map(_transform) } } extension LazyMapCollection : RandomAccessCollection where Base : RandomAccessCollection { } //===--- Support for s.lazy -----------------------------------------------===// extension LazySequenceProtocol { /// Returns a `LazyMapSequence` over this `Sequence`. The elements of /// the result are computed lazily, each time they are read, by /// calling `transform` function on a base element. @inlinable public func map( _ transform: @escaping (Elements.Element) -> U ) -> LazyMapSequence { return LazyMapSequence(_base: self.elements, transform: transform) } } extension LazyCollectionProtocol { /// Returns a `LazyMapCollection` over this `Collection`. The elements of /// the result are computed lazily, each time they are read, by /// calling `transform` function on a base element. @inlinable public func map( _ transform: @escaping (Elements.Element) -> U ) -> LazyMapCollection { return LazyMapCollection(_base: self.elements, transform: transform) } } extension LazyMapCollection { // This overload is needed to re-enable Swift 3 source compatibility related // to a bugfix in ranking behavior of the constraint solver. @available(swift, obsoleted: 4.0) public static func + < Other : LazyCollectionProtocol >(lhs: LazyMapCollection, rhs: Other) -> [Element] where Other.Element == Element { var result: [Element] = [] result.reserveCapacity(numericCast(lhs.count + rhs.count)) result.append(contentsOf: lhs) result.append(contentsOf: rhs) return result } } extension LazyMapSequence { @inlinable @available(swift, introduced: 5) public func map( _ transform: @escaping (Element) -> ElementOfResult ) -> LazyMapSequence { return LazyMapSequence( _base: _base, transform: {transform(self._transform($0))}) } } extension LazyMapCollection { @inlinable @available(swift, introduced: 5) public func map( _ transform: @escaping (Element) -> ElementOfResult ) -> LazyMapCollection { return LazyMapCollection( _base: _base, transform: {transform(self._transform($0))}) } } // @available(*, deprecated, renamed: "LazyMapSequence.Iterator") public typealias LazyMapIterator = LazyMapSequence.Iterator where T: Sequence @available(*, deprecated, renamed: "LazyMapCollection") public typealias LazyMapBidirectionalCollection = LazyMapCollection where T : BidirectionalCollection @available(*, deprecated, renamed: "LazyMapCollection") public typealias LazyMapRandomAccessCollection = LazyMapCollection where T : RandomAccessCollection