Skip to content

Add conditional LazySequenceProtocol conformance #29

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Oct 22, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions Guides/Chain.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@ extension Sequence {
public func chained<S: Sequence>(with other: S) -> Concatenation<Self, S>
where Element == S.Element
}

```

The resulting `Chain` type is a sequence, with conditional conformance to the
`Collection`, `BidirectionalCollection`, and `RandomAccessCollection` when both
the first and second arguments conform.
The resulting `Chain` type is a sequence, with conditional conformance to
`Collection`, `BidirectionalCollection`, and `RandomAccessCollection` when both
the first and second arguments conform. `Chain` also conforms to
`LazySequenceProtocol` when the first argument conforms.

### Naming

Expand Down
3 changes: 2 additions & 1 deletion Guides/Combinations.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ Since the `Combinations` type needs to store an array of the collection’s
indices and mutate the array to generate each permutation, `Combinations` only
has `Sequence` conformance. Adding `Collection` conformance would require
storing the array in the index type, which would in turn lead to copying the
array at every index advancement.
array at every index advancement. `Combinations` does conform to
`LazySequenceProtocol` when the base type conforms.

### Complexity

Expand Down
10 changes: 6 additions & 4 deletions Guides/Cycle.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,12 @@ extension Collection {
```

The new `Cycle` type is a sequence only, given that the `Collection` protocol
design makes infinitely large types impossible/impractical. Note that despite
its name, the returned `FlattenSequence` will always have `Collection`
conformance, and will have `BidirectionalCollection` conformance when called on
a bidirectional collection.
design makes infinitely large types impossible/impractical. `Cycle` also
conforms to `LazySequenceProtocol` when the base type conforms.

Note that despite its name, the returned `FlattenSequence` will always have
`Collection` conformance, and will have `BidirectionalCollection` conformance
when called on a bidirectional collection.

### Complexity

Expand Down
3 changes: 2 additions & 1 deletion Guides/Indexed.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,6 @@ extension Collection {
```

`Indexed` scales from a collection up to a random-access collection, depending on
its base type.
its base type. `Indexed` also conforms to `LazySequenceProtocol` when the base type
conforms.

3 changes: 2 additions & 1 deletion Guides/Permutations.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ Since the `Permutations` type needs to store an array of the collection’s
indices and mutate the array to generate each permutation, `Permutations` only
has `Sequence` conformance. Adding `Collection` conformance would require
storing the array in the index type, which would in turn lead to copying the
array at every index advancement.
array at every index advancement. `Combinations` does conform to
`LazySequenceProtocol` when the base type conforms.

### Complexity

Expand Down
1 change: 1 addition & 0 deletions Sources/Algorithms/Chain.swift
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@ extension Chain: BidirectionalCollection

extension Chain: RandomAccessCollection
where Base1: RandomAccessCollection, Base2: RandomAccessCollection {}
extension Chain: LazySequenceProtocol where Base1: LazySequenceProtocol {}

extension Chain: Equatable where Base1: Equatable, Base2: Equatable {}
extension Chain: Hashable where Base1: Hashable, Base2: Hashable {}
Expand Down
1 change: 1 addition & 0 deletions Sources/Algorithms/Combinations.swift
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ extension Combinations: Sequence {
}
}

extension Combinations: LazySequenceProtocol where Base: LazySequenceProtocol {}
extension Combinations: Equatable where Base: Equatable {}
extension Combinations: Hashable where Base: Hashable {}

Expand Down
10 changes: 3 additions & 7 deletions Sources/Algorithms/Cycle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ extension Cycle: Sequence {
}
}

extension Cycle: LazySequenceProtocol where Base: LazySequenceProtocol {}

//===----------------------------------------------------------------------===//
// cycled()
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -71,13 +73,7 @@ extension Collection {
public func cycled() -> Cycle<Self> {
Cycle(base: self)
}
}

//===----------------------------------------------------------------------===//
// repeated(count:)
//===----------------------------------------------------------------------===//

extension Collection {

/// Returns a sequence that repeats the elements of this collection the
/// specified number of times.
///
Expand Down
5 changes: 5 additions & 0 deletions Sources/Algorithms/Indexed.swift
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,14 @@ extension Indexed: BidirectionalCollection where Base: BidirectionalCollection {
}

extension Indexed: RandomAccessCollection where Base: RandomAccessCollection {}
extension Indexed: LazySequenceProtocol where Base: LazySequenceProtocol {}
extension Indexed: Equatable where Base: Equatable {}
extension Indexed: Hashable where Base: Hashable {}

//===----------------------------------------------------------------------===//
// indexed()
//===----------------------------------------------------------------------===//

extension Collection {
/// Returns a collection of pairs *(i, x)*, where *i* represents an index of
/// the collection, and *x* represents an element.
Expand Down
4 changes: 3 additions & 1 deletion Sources/Algorithms/Permutations.swift
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,8 @@ extension Permutations: Sequence {
}
}

extension Permutations: LazySequenceProtocol where Base: LazySequenceProtocol {}

//===----------------------------------------------------------------------===//
// nextPermutation(by:)
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -177,7 +179,7 @@ extension MutableCollection
}

//===----------------------------------------------------------------------===//
// permutations(count:)
// permutations(ofCount:)
//===----------------------------------------------------------------------===//

extension Collection {
Expand Down
4 changes: 4 additions & 0 deletions Tests/SwiftAlgorithmsTests/ChainTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -136,4 +136,8 @@ final class ChainTests: XCTestCase {
XCTAssertEqual(chain.distance(from: start, to: end), distance)
}
}

func testChainLazy() {
XCTAssertLazy([1, 2, 3].lazy.chained(with: [4, 5, 6]))
}
}
5 changes: 5 additions & 0 deletions Tests/SwiftAlgorithmsTests/ChunkedTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,9 @@ final class ChunkedTests: XCTestCase {
let lazyChunks = fruits.lazy.chunked(by: { $0.first == $1.first })
validateFruitChunks(lazyChunks)
}

func testChunkedLazy() {
XCTAssertLazy(fruits.lazy.chunked(by: { $0.first == $1.first }))
XCTAssertLazy(fruits.lazy.chunked(on: { $0.first }))
}
}
4 changes: 4 additions & 0 deletions Tests/SwiftAlgorithmsTests/CombinationsTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,8 @@ final class CombinationsTests: XCTestCase {
XCTAssertEqualSequences([], "".combinations(ofCount: 5))
XCTAssertEqualSequences([], "ABCD".combinations(ofCount: 5))
}

func testCombinationsLazy() {
XCTAssertLazy("ABC".lazy.combinations(ofCount: 1))
}
}
4 changes: 4 additions & 0 deletions Tests/SwiftAlgorithmsTests/CycleTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,8 @@ final class CycleTests: XCTestCase {
let empty2 = Array("Hello".cycled(times: 0))
XCTAssert(empty2.isEmpty)
}

func testCycleLazy() {
XCTAssertLazy((1...4).lazy.cycled())
}
}
4 changes: 4 additions & 0 deletions Tests/SwiftAlgorithmsTests/IndexedTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,8 @@ final class IndexedTests: XCTestCase {
let indexOfI = si.last(where: { $0.element == "I" })!.index
XCTAssertEqual("I", s[indexOfI])
}

func testIndexedLazy() {
XCTAssertLazy("ABCD".lazy.indexed())
}
}
4 changes: 4 additions & 0 deletions Tests/SwiftAlgorithmsTests/PermutationsTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,8 @@ final class PermutationsTests: XCTestCase {
while numbers.nextPermutation() {}
XCTAssertEqual([1, 2, 3, 4, 5, 6, 7], numbers)
}

func testPermutationsLazy() {
XCTAssertLazy("ABCD".lazy.permutations(ofCount: 2))
}
}
1 change: 1 addition & 0 deletions Tests/SwiftAlgorithmsTests/TestUtilities.swift
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,4 @@ func XCTAssertEqualSequences<S1: Sequence, S2: Sequence>(
try XCTAssert(expression1().elementsEqual(expression2(), by: areEquivalent), message(), file: file, line: line)
}

func XCTAssertLazy<S: LazySequenceProtocol>(_: S) {}