1
- //===--- Filter.swift.gyb -------------------------------------*- swift -*-===//
1
+ //===--- Filter.swift ---- -------------------------------------*- swift -*-===//
2
2
//
3
3
// This source file is part of the Swift.org open source project
4
4
//
10
10
//
11
11
//===----------------------------------------------------------------------===//
12
12
13
- % {
14
- from gyb_stdlib_support import (
15
- collectionForTraversal
16
- )
17
- } %
18
-
19
13
/// An iterator over the elements traversed by some base iterator that also
20
14
/// satisfy a given predicate.
21
15
///
@@ -122,14 +116,6 @@ public struct LazyFilterSequence<Base : Sequence>
122
116
@available ( swift, deprecated: 3.1 , obsoleted: 4.0 , message: " Use Base.Index " )
123
117
public typealias LazyFilterIndex < Base : Collection > = Base . Index
124
118
125
- // FIXME(ABI)#27 (Conditional Conformance): `LazyFilter*Collection` types should be
126
- // collapsed into one `LazyFilterCollection` using conditional conformances.
127
- // Maybe even combined with `LazyFilterSequence`.
128
- // rdar://problem/17144340
129
-
130
- % for Traversal in [ 'Forward', 'Bidirectional'] :
131
- % Self = " LazyFilter " + collectionForTraversal( Traversal)
132
-
133
119
/// A lazy `Collection` wrapper that includes the elements of an
134
120
/// underlying collection that satisfy a predicate.
135
121
///
@@ -140,17 +126,11 @@ public typealias LazyFilterIndex<Base : Collection> = Base.Index
140
126
/// general operations on `LazyFilterCollection` instances may not have the
141
127
/// documented complexity.
142
128
@_fixed_layout // FIXME(sil-serialize-all)
143
- public struct ${ Self} <
144
- Base : ${ collectionForTraversal ( Traversal) }
145
- > : LazyCollectionProtocol, ${ collectionForTraversal ( Traversal) }
146
- {
147
-
148
- /// A type that represents a valid position in the collection.
149
- ///
150
- /// Valid indices consist of the position of every element and a
151
- /// "past the end" position that's not valid for use as a subscript.
152
- public typealias Index = Base . Index
153
-
129
+ public struct LazyFilterCollection < Base : Collection > {
130
+ @_versioned // FIXME(sil-serialize-all)
131
+ internal var _base : Base
132
+ @_versioned // FIXME(sil-serialize-all)
133
+ internal let _predicate : ( Base . Element ) -> Bool
154
134
155
135
/// Creates an instance containing the elements of `base` that
156
136
/// satisfy `isIncluded`.
@@ -163,6 +143,38 @@ public struct ${Self}<
163
143
self . _base = _base
164
144
self . _predicate = isIncluded
165
145
}
146
+ }
147
+
148
+ extension LazyFilterCollection : Sequence {
149
+ public typealias SubSequence = LazyFilterCollection < Base . SubSequence >
150
+ public typealias Element = Base . Element
151
+
152
+ // Any estimate of the number of elements that pass `_predicate` requires
153
+ // iterating the collection and evaluating each element, which can be costly,
154
+ // is unexpected, and usually doesn't pay for itself in saving time through
155
+ // preventing intermediate reallocations. (SR-4164)
156
+ @_inlineable // FIXME(sil-serialize-all)
157
+ public var underestimatedCount : Int { return 0 }
158
+
159
+ @_inlineable // FIXME(sil-serialize-all)
160
+ public func _copyToContiguousArray( )
161
+ -> ContiguousArray < Base . Iterator . Element > {
162
+
163
+ // The default implementation of `_copyToContiguousArray` queries the
164
+ // `count` property, which evaluates `_predicate` for every element --
165
+ // see the note above `underestimatedCount`. Here we treat `self` as a
166
+ // sequence and only rely on underestimated count.
167
+ return _copySequenceToContiguousArray ( self )
168
+ }
169
+
170
+ /// Returns an iterator over the elements of this sequence.
171
+ ///
172
+ /// - Complexity: O(1).
173
+ @_inlineable // FIXME(sil-serialize-all)
174
+ public func makeIterator( ) -> LazyFilterIterator < Base . Iterator > {
175
+ return LazyFilterIterator (
176
+ _base: _base. makeIterator ( ) , _predicate)
177
+ }
166
178
167
179
@_inlineable
168
180
public func _customContainsEquatableElement(
@@ -176,6 +188,14 @@ public struct ${Self}<
176
188
}
177
189
return nil
178
190
}
191
+ }
192
+
193
+ extension LazyFilterCollection : LazyCollectionProtocol , Collection {
194
+ /// A type that represents a valid position in the collection.
195
+ ///
196
+ /// Valid indices consist of the position of every element and a
197
+ /// "past the end" position that's not valid for use as a subscript.
198
+ public typealias Index = Base . Index
179
199
180
200
/// The position of the first element in a non-empty collection.
181
201
///
@@ -221,25 +241,106 @@ public struct ${Self}<
221
241
i = index
222
242
}
223
243
224
- % if Traversal == 'Bidirectional' :
244
+ @ inline ( __always )
225
245
@_inlineable // FIXME(sil-serialize-all)
226
- public func index( before i: Index ) -> Index {
246
+ @_versioned // FIXME(sil-serialize-all)
247
+ internal func _advanceIndex( _ i: inout Index , step: Int ) {
248
+ repeat {
249
+ _base. formIndex ( & i, offsetBy: step)
250
+ } while i != _base. endIndex && !_predicate( _base [ i] )
251
+ }
252
+
253
+ @inline ( __always)
254
+ @_inlineable // FIXME(sil-serialize-all)
255
+ @_versioned // FIXME(sil-serialize-all)
256
+ internal func _ensureBidirectional( step: Int ) {
257
+ // FIXME: This seems to be the best way of checking whether _base is
258
+ // forward only without adding an extra protocol requirement.
259
+ // index(_:offsetBy:limitedBy:) is chosen becuase it is supposed to return
260
+ // nil when the resulting index lands outside the collection boundaries,
261
+ // and therefore likely does not trap in these cases.
262
+ if step < 0 {
263
+ _ = _base. index (
264
+ _base. endIndex, offsetBy: step, limitedBy: _base. startIndex)
265
+ }
266
+ }
267
+
268
+ @_inlineable // FIXME(sil-serialize-all)
269
+ public func distance( from start: Index , to end: Index ) -> Int {
270
+ // The following line makes sure that distance(from:to:) is invoked on the
271
+ // _base at least once, to trigger a _precondition in forward only
272
+ // collections.
273
+ _ = _base. distance ( from: start, to: end)
274
+ var _start : Index
275
+ let _end : Index
276
+ let step : Int
277
+ if start > end {
278
+ _start = end
279
+ _end = start
280
+ step = - 1
281
+ }
282
+ else {
283
+ _start = start
284
+ _end = end
285
+ step = 1
286
+ }
287
+ var count = 0
288
+ while _start != _end {
289
+ count += step
290
+ formIndex ( after: & _start)
291
+ }
292
+ return count
293
+ }
294
+
295
+ @_inlineable // FIXME(sil-serialize-all)
296
+ public func index( _ i: Index , offsetBy n: Int ) -> Index {
227
297
var i = i
228
- formIndex ( before: & i)
298
+ let step = n. signum ( )
299
+ // The following line makes sure that index(_:offsetBy:) is invoked on the
300
+ // _base at least once, to trigger a _precondition in forward only
301
+ // collections.
302
+ _ensureBidirectional ( step: step)
303
+ for _ in 0 ..< abs ( numericCast ( n) ) {
304
+ _advanceIndex ( & i, step: step)
305
+ }
229
306
return i
230
307
}
231
308
232
309
@_inlineable // FIXME(sil-serialize-all)
233
- public func formIndex( before i: inout Index ) {
234
- // TODO: swift-3-indexing-model: _failEarlyRangeCheck i?
235
- var index = i
236
- _precondition ( index != _base. startIndex, " Can't retreat before startIndex " )
237
- repeat {
238
- _base. formIndex ( before: & index)
239
- } while !_predicate( _base [ index] )
240
- i = index
310
+ public func formIndex( _ i: inout Index , offsetBy n: Int ) {
311
+ i = index ( i, offsetBy: n)
312
+ }
313
+
314
+ @_inlineable // FIXME(sil-serialize-all)
315
+ public func index(
316
+ _ i: Index , offsetBy n: Int , limitedBy limit: Index
317
+ ) -> Index ? {
318
+ var i = i
319
+ let step = n. signum ( )
320
+ // The following line makes sure that index(_:offsetBy:limitedBy:) is
321
+ // invoked on the _base at least once, to trigger a _precondition in
322
+ // forward only collections.
323
+ _ensureBidirectional ( step: step)
324
+ for _ in 0 ..< abs ( numericCast ( n) ) {
325
+ if i == limit {
326
+ return nil
327
+ }
328
+ _advanceIndex ( & i, step: step)
329
+ }
330
+ return i
331
+ }
332
+
333
+ @_inlineable // FIXME(sil-serialize-all)
334
+ public func formIndex(
335
+ _ i: inout Index , offsetBy n: Int , limitedBy limit: Index
336
+ ) -> Bool {
337
+ if let advancedIndex = index ( i, offsetBy: n, limitedBy: limit) {
338
+ i = advancedIndex
339
+ return true
340
+ }
341
+ i = limit
342
+ return false
241
343
}
242
- % end
243
344
244
345
/// Accesses the element at `position`.
245
346
///
@@ -250,48 +351,34 @@ public struct ${Self}<
250
351
return _base [ position]
251
352
}
252
353
253
- public typealias SubSequence = ${ Self} < Base . SubSequence>
254
-
255
354
@_inlineable // FIXME(sil-serialize-all)
256
355
public subscript( bounds: Range < Index > ) -> SubSequence {
257
356
return SubSequence ( _base: _base [ bounds] , _predicate)
258
357
}
358
+ }
259
359
260
- // Any estimate of the number of elements that pass `_predicate` requires
261
- // iterating the collection and evaluating each element, which can be costly,
262
- // is unexpected, and usually doesn't pay for itself in saving time through
263
- // preventing intermediate reallocations. (SR-4164)
264
- @_inlineable // FIXME(sil-serialize-all)
265
- public var underestimatedCount : Int { return 0 }
360
+ extension LazyFilterCollection : BidirectionalCollection
361
+ where Base : BidirectionalCollection {
266
362
267
363
@_inlineable // FIXME(sil-serialize-all)
268
- public func _copyToContiguousArray( )
269
- -> ContiguousArray < Base . Iterator . Element > {
270
-
271
- // The default implementation of `_copyToContiguousArray` queries the
272
- // `count` property, which evaluates `_predicate` for every element --
273
- // see the note above `underestimatedCount`. Here we treat `self` as a
274
- // sequence and only rely on underestimated count.
275
- return _copySequenceToContiguousArray ( self )
364
+ public func index( before i: Index ) -> Index {
365
+ var i = i
366
+ formIndex ( before: & i)
367
+ return i
276
368
}
277
369
278
- /// Returns an iterator over the elements of this sequence.
279
- ///
280
- /// - Complexity: O(1).
281
370
@_inlineable // FIXME(sil-serialize-all)
282
- public func makeIterator( ) -> LazyFilterIterator < Base . Iterator > {
283
- return LazyFilterIterator (
284
- _base: _base. makeIterator ( ) , _predicate)
371
+ public func formIndex( before i: inout Index ) {
372
+ // TODO: swift-3-indexing-model: _failEarlyRangeCheck i?
373
+ var index = i
374
+ _precondition ( index != _base. startIndex, " Can't retreat before startIndex " )
375
+ repeat {
376
+ _base. formIndex ( before: & index)
377
+ } while !_predicate( _base [ index] )
378
+ i = index
285
379
}
286
-
287
- @_versioned // FIXME(sil-serialize-all)
288
- internal var _base : Base
289
- @_versioned // FIXME(sil-serialize-all)
290
- internal let _predicate : ( Base . Element ) -> Bool
291
380
}
292
381
293
- % end
294
-
295
382
extension LazySequenceProtocol {
296
383
/// Returns the elements of `self` that satisfy `isIncluded`.
297
384
///
@@ -303,20 +390,11 @@ extension LazySequenceProtocol {
303
390
public func filter(
304
391
_ isIncluded: @escaping ( Elements . Element ) -> Bool
305
392
) -> LazyFilterSequence < Self . Elements > {
306
- return LazyFilterSequence (
307
- _base: self . elements, isIncluded)
393
+ return LazyFilterSequence ( _base: self . elements, isIncluded)
308
394
}
309
395
}
310
396
311
- % for Traversal in [ 'Forward', 'Bidirectional'] :
312
-
313
- extension LazyCollectionProtocol
314
- % if Traversal != 'Forward':
315
- where
316
- Self : ${ collectionForTraversal ( Traversal) } ,
317
- Elements : ${ collectionForTraversal ( Traversal) }
318
- % end
319
- {
397
+ extension LazyCollectionProtocol {
320
398
/// Returns the elements of `self` that satisfy `predicate`.
321
399
///
322
400
/// - Note: The elements of the result are computed on-demand, as
@@ -326,14 +404,10 @@ extension LazyCollectionProtocol
326
404
@_inlineable // FIXME(sil-serialize-all)
327
405
public func filter(
328
406
_ isIncluded: @escaping ( Elements . Element ) -> Bool
329
- ) -> LazyFilter ${ collectionForTraversal( Traversal) } < Self . Elements > {
330
- return LazyFilter ${ collectionForTraversal ( Traversal) } (
331
- _base: self . elements, isIncluded)
407
+ ) -> LazyFilterCollection < Self . Elements > {
408
+ return LazyFilterCollection ( _base: self . elements, isIncluded)
332
409
}
333
410
}
334
411
335
- % end
336
-
337
- // ${'Local Variables'}:
338
- // eval: (read-only-mode 1)
339
- // End:
412
+ @available ( * , deprecated, renamed: " LazyFilterCollection " )
413
+ public typealias LazyFilterBidirectionalCollection < T> = LazyFilterCollection < T > where T : BidirectionalCollection
0 commit comments