taler-ios

iOS apps for GNU Taler (wallet)
Log | Files | Refs | README | LICENSE

Zip3Sequence.swift (6396B)


      1 /// Copyright 2016 Alexander Momchilov
      2 ///
      3 /// Licensed under the Apache License, Version 2.0 (the "License");
      4 /// you may not use this file except in compliance with the License.
      5 /// You may obtain a copy of the License at
      6 ///
      7 /// http://www.apache.org/licenses/LICENSE-2.0
      8 ///
      9 /// Unless required by applicable law or agreed to in writing, software
     10 /// distributed under the License is distributed on an "AS IS" BASIS,
     11 /// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 /// See the License for the specific language governing permissions and limitations under the License.
     13 
     14 /// Creates a sequence of tuples built out of 3 underlying sequences.
     15 ///
     16 /// In the `Zip3Sequence` instance returned by this function, the elements of
     17 /// the *i*th tuple are the *i*th elements of each underlying sequence. The
     18 /// following example uses the `zip(_:_:)` function to iterate over an array
     19 /// of strings and a countable range at the same time:
     20 ///
     21 ///     let words = ["one", "two", "three", "four"]
     22 ///     let numbers = 1...4
     23 ///
     24 ///     for (word, number) in zip(words, numbers) {
     25 ///         print("\(word): \(number)")
     26 ///     }
     27 ///     // Prints "one: 1"
     28 ///     // Prints "two: 2
     29 ///     // Prints "three: 3"
     30 ///     // Prints "four: 4"
     31 ///
     32 /// If the 3 sequences passed to `zip(_:_:_:)` are different lengths, the
     33 /// resulting sequence is the same length as the shortest sequence. In this
     34 /// example, the resulting array is the same length as `words`:
     35 ///
     36 ///     let naturalNumbers = 1...Int.max
     37 ///     let zipped = Array(zip(words, naturalNumbers))
     38 ///     // zipped == [("one", 1), ("two", 2), ("three", 3), ("four", 4)]
     39 ///
     40 /// - Parameters:
     41 ///   - sequence1: The sequence or collection in position 1 of each tuple.
     42 ///   - sequence2: The sequence or collection in position 2 of each tuple.
     43 ///   - sequence3: The sequence or collection in position 3 of each tuple.
     44 /// - Returns: A sequence of tuple pairs, where the elements of each pair are
     45 ///   corresponding elements of `sequence1` and `sequence2`.
     46 public func zip<Sequence1 : Sequence,
     47                 Sequence2 : Sequence,
     48                 Sequence3 : Sequence
     49             >(  _ sequence1: Sequence1,
     50                 _ sequence2: Sequence2,
     51                 _ sequence3: Sequence3
     52             ) -> Zip3Sequence<
     53                 Sequence1,
     54                 Sequence2,
     55                 Sequence3
     56             > {
     57     Zip3Sequence(_sequence1: sequence1,
     58                  _sequence2: sequence2,
     59                  _sequence3: sequence3)
     60 }
     61 
     62 /// An iterator for `Zip3Sequence`.
     63 public struct Zip3Iterator<Iterator1 : IteratorProtocol,
     64                            Iterator2 : IteratorProtocol,
     65                            Iterator3 : IteratorProtocol
     66               > : IteratorProtocol {
     67     /// The type of element returned by `next()`.
     68     public typealias Element = (Iterator1.Element,
     69                                 Iterator2.Element,
     70                                 Iterator3.Element)
     71 
     72     /// Creates an instance around the underlying iterators.
     73     internal init(_ iterator1: Iterator1,
     74                   _ iterator2: Iterator2,
     75                   _ iterator3: Iterator3
     76     ) {
     77         _baseStream1 = iterator1
     78         _baseStream2 = iterator2
     79         _baseStream3 = iterator3
     80     }
     81 
     82     /// Advances to the next element and returns it, or `nil` if no next element exists.
     83     /// Once `nil` has been returned, all subsequent calls return `nil`.
     84     public mutating func next() -> Element? {
     85         // The next() function needs to track if it has reached the end.  If we
     86         // didn't, and the first sequence is longer than the second, then when we
     87         // have already exhausted the second sequence, on every subsequent call to
     88         // next() we would consume and discard one additional element from the
     89         // first sequence, even though next() had already returned nil.
     90 
     91         if _reachedEnd {
     92             return nil
     93         }
     94 
     95         guard let element1 = _baseStream1.next(),
     96               let element2 = _baseStream2.next(),
     97               let element3 = _baseStream3.next()
     98         else {
     99             _reachedEnd = true
    100             return nil
    101         }
    102 
    103         return (element1, element2, element3)
    104     }
    105 
    106     internal var _baseStream1: Iterator1
    107     internal var _baseStream2: Iterator2
    108     internal var _baseStream3: Iterator3
    109     internal var _reachedEnd: Bool = false
    110 }
    111 
    112 /// A sequence of pairs built out of two underlying sequences.
    113 ///
    114 /// In a `Zip3Sequence` instance, the elements of the *i*th pair are the *i*th
    115 /// elements of each underlying sequence. To create a `Zip3Sequence` instance,
    116 /// use the `zip(_:_:_:)` function.
    117 ///
    118 /// The following example uses the `zip(_:_:)` function to iterate over an
    119 /// array of strings and a countable range at the same time:
    120 ///
    121 ///     let words = ["one", "two", "three", "four"]
    122 ///     let numbers = 1...4
    123 ///
    124 ///     for (word, number) in zip(words, numbers) {
    125 ///         print("\(word): \(number)")
    126 ///     }
    127 ///     // Prints "one: 1"
    128 ///     // Prints "two: 2
    129 ///     // Prints "three: 3"
    130 ///     // Prints "four: 4"
    131 ///
    132 /// - SeeAlso: `zip(_:_:_:)`
    133 public struct Zip3Sequence<Sequence1 : Sequence,
    134                            Sequence2 : Sequence,
    135                            Sequence3 : Sequence> : Sequence {
    136 
    137     public typealias Stream1 = Sequence1.Iterator
    138     public typealias Stream2 = Sequence2.Iterator
    139     public typealias Stream3 = Sequence3.Iterator
    140 
    141     /// A type whose instances can produce the elements of this sequence, in order.
    142     public typealias Iterator = Zip3Iterator<Stream1, Stream2, Stream3>
    143 
    144     @available(*, unavailable, renamed: "Iterator")
    145     public typealias Generator = Iterator
    146 
    147     /// Creates an instance that makes pairs of elements from `sequence1` and `sequence2`.
    148     public // @testable
    149     init(_sequence1 sequence1: Sequence1,
    150          _sequence2 sequence2: Sequence2,
    151          _sequence3 sequence3: Sequence3
    152     ) {
    153         _sequence1 = sequence1
    154         _sequence2 = sequence2
    155         _sequence3 = sequence3
    156     }
    157 
    158     /// Returns an iterator over the elements of this sequence.
    159     public func makeIterator() -> Iterator {
    160         Iterator(_sequence1.makeIterator(),
    161                  _sequence2.makeIterator(),
    162                  _sequence3.makeIterator())
    163     }
    164 
    165     internal let _sequence1: Sequence1
    166     internal let _sequence2: Sequence2
    167     internal let _sequence3: Sequence3
    168 }