Skip to content

Commit b0f3020

Browse files
breakfastbreakfast
breakfast
authored and
breakfast
committed
Split sequence & collection types
1 parent 03e37de commit b0f3020

File tree

1 file changed

+147
-55
lines changed

1 file changed

+147
-55
lines changed

Sources/Algorithms/AdjacentPairs.swift

+147-55
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
extension Sequence {
1313
/// Creates a sequence of adjacent pairs of elements from this sequence.
1414
///
15-
/// In the `AdjacentPairs` instance returned by this method, the elements of
15+
/// In the `AdjacentPairsSequence` returned by this method, the elements of
1616
/// the *i*th pair are the *i*th and *(i+1)*th elements of the underlying
1717
/// sequence.
1818
/// The following example uses the `adjacentPairs()` method to iterate over
@@ -25,14 +25,37 @@ extension Sequence {
2525
/// // Prints "(2, 3)"
2626
/// // Prints "(3, 4)"
2727
/// // Prints "(4, 5)"
28-
public func adjacentPairs() -> AdjacentPairs<Self> {
29-
AdjacentPairs(_base: self)
28+
@inlinable
29+
public func adjacentPairs() -> AdjacentPairsSequence<Self> {
30+
AdjacentPairsSequence(base: self)
31+
}
32+
}
33+
34+
extension Collection {
35+
/// A collection of adjacent pairs of elements built from an underlying collection.
36+
///
37+
/// In an `AdjacentPairsCollection`, the elements of the *i*th pair are the *i*th
38+
/// and *(i+1)*th elements of the underlying sequence. The following example
39+
/// uses the `adjacentPairs()` method to iterate over adjacent pairs of
40+
/// integers:
41+
/// ```
42+
/// for pair in (1...5).adjacentPairs() {
43+
/// print(pair)
44+
/// }
45+
/// // Prints "(1, 2)"
46+
/// // Prints "(2, 3)"
47+
/// // Prints "(3, 4)"
48+
/// // Prints "(4, 5)"
49+
/// ```
50+
@inlinable
51+
public func adjacentPairs() -> AdjacentPairsCollection<Self> {
52+
AdjacentPairsCollection(base: self)
3053
}
3154
}
3255

3356
/// A sequence of adjacent pairs of elements built from an underlying sequence.
3457
///
35-
/// In an `AdjacentPairs` sequence, the elements of the *i*th pair are the *i*th
58+
/// In an `AdjacentPairsSequence`, the elements of the *i*th pair are the *i*th
3659
/// and *(i+1)*th elements of the underlying sequence. The following example
3760
/// uses the `adjacentPairs()` method to iterate over adjacent pairs of
3861
/// integers:
@@ -45,135 +68,204 @@ extension Sequence {
4568
/// // Prints "(3, 4)"
4669
/// // Prints "(4, 5)"
4770
/// ```
48-
public struct AdjacentPairs<Base: Sequence> {
49-
internal let _base: Base
71+
public struct AdjacentPairsSequence<Base: Sequence> {
72+
@usableFromInline
73+
internal let base: Base
5074

5175
/// Creates an instance that makes pairs of adjacent elements from `base`.
52-
internal init(_base: Base) {
53-
self._base = _base
76+
@inlinable
77+
internal init(base: Base) {
78+
self.base = base
5479
}
5580
}
5681

57-
// MARK: - Sequence
58-
59-
extension AdjacentPairs {
82+
extension AdjacentPairsSequence {
6083
public struct Iterator {
61-
internal var _base: Base.Iterator
62-
internal var _previousElement: Base.Element?
84+
@usableFromInline
85+
internal var base: Base.Iterator
6386

64-
internal init(_base: Base.Iterator) {
65-
self._base = _base
66-
self._previousElement = self._base.next()
87+
@usableFromInline
88+
internal var previousElement: Base.Element?
89+
90+
@inlinable
91+
internal init(base: Base.Iterator) {
92+
self.base = base
6793
}
6894
}
6995
}
7096

71-
extension AdjacentPairs.Iterator: IteratorProtocol {
97+
extension AdjacentPairsSequence.Iterator: IteratorProtocol {
7298
public typealias Element = (Base.Element, Base.Element)
7399

100+
@inlinable
74101
public mutating func next() -> Element? {
75-
guard let previous = _previousElement, let next = _base.next() else {
102+
if previousElement == nil {
103+
previousElement = base.next()
104+
}
105+
106+
guard let previous = previousElement, let next = base.next() else {
76107
return nil
77108
}
78-
_previousElement = next
109+
110+
previousElement = next
79111
return (previous, next)
80112
}
81113
}
82114

83-
extension AdjacentPairs: Sequence {
115+
extension AdjacentPairsSequence: Sequence {
116+
@inlinable
84117
public func makeIterator() -> Iterator {
85-
Iterator(_base: _base.makeIterator())
118+
Iterator(base: base.makeIterator())
86119
}
87120

121+
@inlinable
88122
public var underestimatedCount: Int {
89-
Swift.max(0, _base.underestimatedCount - 1)
123+
Swift.max(0, base.underestimatedCount - 1)
90124
}
91125
}
92126

93-
// MARK: - Collection
127+
/// A collection of adjacent pairs of elements built from an underlying collection.
128+
///
129+
/// In an `AdjacentPairsCollection`, the elements of the *i*th pair are the *i*th
130+
/// and *(i+1)*th elements of the underlying sequence. The following example
131+
/// uses the `adjacentPairs()` method to iterate over adjacent pairs of
132+
/// integers:
133+
/// ```
134+
/// for pair in (1...5).adjacentPairs() {
135+
/// print(pair)
136+
/// }
137+
/// // Prints "(1, 2)"
138+
/// // Prints "(2, 3)"
139+
/// // Prints "(3, 4)"
140+
/// // Prints "(4, 5)"
141+
/// ```
142+
public struct AdjacentPairsCollection<Base: Collection> {
143+
@usableFromInline
144+
internal let base: Base
145+
146+
public let startIndex: Index
147+
148+
@inlinable
149+
internal init(base: Base) {
150+
self.base = base
151+
152+
// Precompute `startIndex` to ensure O(1) behavior,
153+
// avoiding indexing past `endIndex`
154+
let start = base.startIndex
155+
let end = base.endIndex
156+
let second = start == end ? start : base.index(after: start)
157+
self.startIndex = Index(first: start, second: second)
158+
}
159+
}
160+
161+
extension AdjacentPairsCollection {
162+
public typealias Iterator = AdjacentPairsSequence<Base>.Iterator
163+
164+
@inlinable
165+
public func makeIterator() -> Iterator {
166+
Iterator(base: base.makeIterator())
167+
}
168+
}
94169

95-
extension AdjacentPairs where Base: Collection {
170+
extension AdjacentPairsCollection {
96171
public struct Index: Comparable {
97-
internal var _base: Base.Index
172+
@usableFromInline
173+
internal var first: Base.Index
174+
175+
@usableFromInline
176+
internal var second: Base.Index
98177

99-
internal init(_base: Base.Index) {
100-
self._base = _base
178+
@inlinable
179+
internal init(first: Base.Index, second: Base.Index) {
180+
self.first = first
181+
self.second = second
101182
}
102183

184+
@inlinable
103185
public static func < (lhs: Index, rhs: Index) -> Bool {
104-
lhs._base < rhs._base
186+
(lhs.first, lhs.second) < (rhs.first, rhs.second)
105187
}
106188
}
107189
}
108190

109-
extension AdjacentPairs: Collection where Base: Collection {
110-
public var startIndex: Index { Index(_base: _base.startIndex) }
111-
191+
extension AdjacentPairsCollection: Collection {
192+
@inlinable
112193
public var endIndex: Index {
113-
switch _base.endIndex {
114-
case _base.startIndex, _base.index(after: _base.startIndex):
115-
return Index(_base: _base.startIndex)
116-
case let endIndex:
117-
return Index(_base: endIndex)
194+
switch base.endIndex {
195+
case startIndex.first, startIndex.second:
196+
return startIndex
197+
case let end:
198+
return Index(first: end, second: end)
118199
}
119200
}
120201

202+
@inlinable
121203
public subscript(position: Index) -> (Base.Element, Base.Element) {
122-
(_base[position._base], _base[_base.index(after: position._base)])
204+
(base[position.first], base[position.second])
123205
}
124206

207+
@inlinable
125208
public func index(after i: Index) -> Index {
126-
let next = _base.index(after: i._base)
127-
return _base.index(after: next) == _base.endIndex
209+
let next = base.index(after: i.second)
210+
return next == base.endIndex
128211
? endIndex
129-
: Index(_base: next)
212+
: Index(first: i.second, second: next)
130213
}
131214

215+
@inlinable
132216
public func index(_ i: Index, offsetBy distance: Int) -> Index {
133217
if distance == 0 {
134218
return i
135219
} else if distance > 0 {
136-
let offsetIndex = _base.index(i._base, offsetBy: distance)
137-
return _base.index(after: offsetIndex) == _base.endIndex
220+
let firstOffsetIndex = base.index(i.first, offsetBy: distance)
221+
let secondOffsetIndex = base.index(after: firstOffsetIndex)
222+
return secondOffsetIndex == base.endIndex
138223
? endIndex
139-
: Index(_base: offsetIndex)
224+
: Index(first: firstOffsetIndex, second: secondOffsetIndex)
140225
} else {
141226
return i == endIndex
142-
? Index(_base: _base.index(i._base, offsetBy: distance - 1))
143-
: Index(_base: _base.index(i._base, offsetBy: distance))
227+
? Index(first: base.index(i.first, offsetBy: distance - 1),
228+
second: base.index(i.first, offsetBy: distance))
229+
: Index(first: base.index(i.first, offsetBy: distance),
230+
second: i.first)
144231
}
145232
}
146233

234+
@inlinable
147235
public func distance(from start: Index, to end: Index) -> Int {
148236
let offset: Int
149-
switch (start._base, end._base) {
150-
case (_base.endIndex, _base.endIndex):
237+
switch (start.first, end.first) {
238+
case (base.endIndex, base.endIndex):
151239
return 0
152-
case (_base.endIndex, _):
240+
case (base.endIndex, _):
153241
offset = +1
154-
case (_, _base.endIndex):
242+
case (_, base.endIndex):
155243
offset = -1
156244
default:
157245
offset = 0
158246
}
159247

160-
return _base.distance(from: start._base, to: end._base) + offset
248+
return base.distance(from: start.first, to: end.first) + offset
161249
}
162250

251+
@inlinable
163252
public var count: Int {
164-
Swift.max(0, _base.count - 1)
253+
Swift.max(0, base.count - 1)
165254
}
166255
}
167256

168-
extension AdjacentPairs: BidirectionalCollection
257+
extension AdjacentPairsCollection: BidirectionalCollection
169258
where Base: BidirectionalCollection
170259
{
260+
@inlinable
171261
public func index(before i: Index) -> Index {
172262
i == endIndex
173-
? Index(_base: _base.index(i._base, offsetBy: -2))
174-
: Index(_base: _base.index(before: i._base))
263+
? Index(first: base.index(i.first, offsetBy: -2),
264+
second: base.index(before: i.first))
265+
: Index(first: base.index(before: i.first),
266+
second: i.first)
175267
}
176268
}
177269

178-
extension AdjacentPairs: RandomAccessCollection
270+
extension AdjacentPairsCollection: RandomAccessCollection
179271
where Base: RandomAccessCollection {}

0 commit comments

Comments
 (0)