Skip to content

Commit 310c9c9

Browse files
authored
Merge pull request #26778 from natecook1000/nate/concatenation_sequence
2 parents 818d0f5 + 2e6f865 commit 310c9c9

File tree

1 file changed

+50
-22
lines changed

1 file changed

+50
-22
lines changed

test/Prototypes/Algorithms.swift

Lines changed: 50 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -274,42 +274,59 @@ extension MutableCollection where Self: RandomAccessCollection {
274274
}
275275
}
276276

277-
//===--- ConcatenatedCollection -------------------------------------------===//
277+
//===--- Concatenation ----------------------------------------------------===//
278278
//===----------------------------------------------------------------------===//
279279

280-
// ConcatenatedCollection improves on a flattened array or other collection by
280+
// Concatenation improves on a flattened array or other collection by
281281
// allowing random-access traversal if the underlying collections are
282282
// random-access.
283-
//
284-
// Q: Add a ConcatenatedSequence for consistency? Would be nice to be able to
285-
// call `let seqAB = concatenate(seqA, seqB)`.
286283

287-
/// A concatenation of two collections with the same element type.
288-
public struct Concatenation<C1 : Collection, C2: Collection>: Collection
289-
where C1.Element == C2.Element
284+
/// A concatenation of two sequences with the same element type.
285+
public struct Concatenation<Base1: Sequence, Base2: Sequence>: Sequence
286+
where Base1.Element == Base2.Element
290287
{
291-
let _base1: C1
292-
let _base2: C2
288+
let _base1: Base1
289+
let _base2: Base2
293290

294-
init(_base1: C1, base2: C2) {
291+
init(_base1: Base1, base2: Base2) {
295292
self._base1 = _base1
296293
self._base2 = base2
297294
}
295+
296+
public struct Iterator: IteratorProtocol {
297+
var _iterator1: Base1.Iterator
298+
var _iterator2: Base2.Iterator
299+
300+
init(_ concatenation: Concatenation) {
301+
_iterator1 = concatenation._base1.makeIterator()
302+
_iterator2 = concatenation._base2.makeIterator()
303+
}
304+
305+
public mutating func next() -> Base1.Element? {
306+
return _iterator1.next() ?? _iterator2.next()
307+
}
308+
}
309+
310+
public func makeIterator() -> Iterator {
311+
Iterator(self)
312+
}
313+
}
298314

315+
extension Concatenation: Collection where Base1: Collection, Base2: Collection {
299316
/// A position in a `Concatenation`.
300317
public struct Index : Comparable {
301318
internal enum _Representation : Equatable {
302-
case first(C1.Index)
303-
case second(C2.Index)
319+
case first(Base1.Index)
320+
case second(Base2.Index)
304321
}
305322

306323
/// Creates a new index into the first underlying collection.
307-
internal init(first i: C1.Index) {
324+
internal init(first i: Base1.Index) {
308325
_position = .first(i)
309326
}
310327

311328
/// Creates a new index into the second underlying collection.
312-
internal init(second i: C2.Index) {
329+
internal init(second i: Base2.Index) {
313330
_position = .second(i)
314331
}
315332

@@ -341,7 +358,7 @@ public struct Concatenation<C1 : Collection, C2: Collection>: Collection
341358
return Index(second: _base2.endIndex)
342359
}
343360

344-
public subscript(i: Index) -> C1.Element {
361+
public subscript(i: Index) -> Base1.Element {
345362
switch i._position {
346363
case let .first(i):
347364
return _base1[i]
@@ -365,7 +382,7 @@ public struct Concatenation<C1 : Collection, C2: Collection>: Collection
365382
}
366383

367384
extension Concatenation : BidirectionalCollection
368-
where C1: BidirectionalCollection, C2: BidirectionalCollection
385+
where Base1: BidirectionalCollection, Base2: BidirectionalCollection
369386
{
370387
public func index(before i: Index) -> Index {
371388
assert(i != startIndex, "Can't advance before startIndex")
@@ -381,7 +398,7 @@ extension Concatenation : BidirectionalCollection
381398
}
382399

383400
extension Concatenation : RandomAccessCollection
384-
where C1: RandomAccessCollection, C2: RandomAccessCollection
401+
where Base1: RandomAccessCollection, Base2: RandomAccessCollection
385402
{
386403
public func index(_ i: Index, offsetBy n: Int) -> Index {
387404
if n == 0 { return i }
@@ -425,14 +442,22 @@ extension Concatenation : RandomAccessCollection
425442

426443
/// Returns a new collection that presents a view onto the elements of the
427444
/// first collection and then the elements of the second collection.
428-
func concatenate<C1 : Collection, C2 : Collection>(
429-
_ first: C1,
430-
_ second: C2)
431-
-> Concatenation<C1, C2> where C1.Element == C2.Element
445+
func concatenate<S1: Sequence, S2: Sequence>(
446+
_ first: S1,
447+
_ second: S2)
448+
-> Concatenation<S1, S2> where S1.Element == S2.Element
432449
{
433450
return Concatenation(_base1: first, base2: second)
434451
}
435452

453+
extension Sequence {
454+
func followed<S: Sequence>(by other: S) -> Concatenation<Self, S>
455+
where Element == S.Element
456+
{
457+
return concatenate(self, other)
458+
}
459+
}
460+
436461
//===--- RotatedCollection ------------------------------------------------===//
437462
//===----------------------------------------------------------------------===//
438463

@@ -763,6 +788,9 @@ suite.test("concatenate") {
763788
let w = "world!"
764789
let hw = concatenate(h, w)
765790
expectEqual("Hello, world!", String(hw))
791+
792+
let run = (1...).prefix(10).followed(by: 20...)
793+
expectEqual(Array(run.prefix(20)), Array(1...10) + (20..<30))
766794
}
767795

768796
suite.test("stablePartition") {

0 commit comments

Comments
 (0)