# Transitioning a lazy sequence to a collection

**URL:** <https://forums.swift.org/t/transitioning-a-lazy-sequence-to-a-collection/19685>\
**Category:** Using Swift\
**Tags:** collection, lazy\
**Created:** [January 22, 2019, 1:00am UTC](https://forums.swift.org/t/transitioning-a-lazy-sequence-to-a-collection/19685 "2019-01-22T01:00:46Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![CTMacUser](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/ctmacuser/32/1802_2.png) [@CTMacUser](https://forums.swift.org/u/CTMacUser)\
**Post date:** [January 22, 2019, 1:00am UTC](https://forums.swift.org/t/transitioning-a-lazy-sequence-to-a-collection/19685/1 "2019-01-22T01:00:46Z")

</div>

I've tried making `Sequence` extended methods to simulate C++'s `std::unique_copy`, and I'm trying to make a lazy variant.

```
/// An iterator that vends only the elements of the wrapped iterator that don't preceed an element with an equivalent value.
public struct LazyFilterAdjacentValuesIterator<Base: IteratorProtocol> {
    var base: Base
    let areEquivalent: (Base.Element, Base.Element) -> Bool
    var last: Base.Element? = nil

    /// Creates an iterator wrapping the given one, along with the equivalence relation for testing.
    init(_ base: Base, by areEquivalent: @escaping (Base.Element, Base.Element) -> Bool) {
        self.base = base
        self.areEquivalent = areEquivalent
    }
}

extension LazyFilterAdjacentValuesIterator: IteratorProtocol {
    public mutating func next() -> Base.Element? {
        while let element = base.next() {
            if let lastElement = last, areEquivalent(lastElement, element) {
                continue
            }
            last = element
            return element
        }
        return nil
    }
}

/// A sequence that vends only the elements of the wrapped sequence that don't preceed an element with an equivalent value.
public struct LazyFilterAdjacentValuesSequence<Base: Sequence> {
    let base: Base
    let areEquivalent: (Base.Element, Base.Element) -> Bool
}

extension LazyFilterAdjacentValuesSequence: Sequence {
    public func makeIterator() -> LazyFilterAdjacentValuesIterator<Base.Iterator> {
        return LazyFilterAdjacentValuesIterator(base.makeIterator(), by: areEquivalent)
    }
    public var underestimatedCount: Int { return base.underestimatedCount.signum() }
}

extension LazyFilterAdjacentValuesSequence: LazySequenceProtocol {}

extension LazySequenceProtocol {
    /// Returns the elements of `self` that are not equivalent to their predecessor, using the given predicate as the equivalence test.
    public func filterAdjacentValues(by areEquivalent: @escaping (Element, Element) -> Bool) -> LazyFilterAdjacentValuesSequence<Elements> {
        return LazyFilterAdjacentValuesSequence(base: elements, areEquivalent: areEquivalent)
    }
}

extension LazySequenceProtocol where Element: Equatable {
    /// Returns the elements of `self` that are not equal to their predecessor.
    public func filterAdjacentValues() -> LazyFilterAdjacentValuesSequence<Elements> {
        return filterAdjacentValues(by: ==)
    }
}

```

I noticed that `LazySequenceProtocol.map` and `filter` have a special mode to have those sequences act like collections when the wrapped sequence is also a collection. I tried that:

```
extension LazyFilterAdjacentValuesSequence: Collection where Base: Collection {
    public var startIndex: Base.Index { return base.startIndex }
    public var endIndex: Base.Index { return base.endIndex }
    public subscript(position: Base.Index) -> Base.Element { return base[position] }
    public func index(after i: Base.Index) -> Base.Index {
        return base[base.index(after: i)...].firstIndex(where: { !areEquivalent(base[i], $0) }) ?? endIndex
    }
}

```

I did have a type-alias of "`LazyFilterAdjacentValuesCollection<T: Collection> = LazyFilterAdjacentValuesSequence<T>`," with an `extension` on `LazyFilterAdjacentValuesCollection` unconditionally conforming to `Collection` but it didn't make a difference on the errors I got:

- `Type 'AnySequence<Base.Element>' does not conform to protocol 'Collection'`
- `Type 'LazyFilterAdjacentValuesSequence<Base>' does not conform to protocol 'Collection'`

What is the Standard Library doing right that I'm doing wrong? (I'm using Xcode 10.1, with Swift 4.2.)

---

<div class="post-metadata">

**Author:** ![ASwiftUser](https://avatars.discourse-cdn.com/v4/letter/a/3da27b/32.png) [@ASwiftUser](https://forums.swift.org/u/ASwiftUser)\
**Post date:** [January 23, 2019, 11:59pm UTC](https://forums.swift.org/t/transitioning-a-lazy-sequence-to-a-collection/19685/2 "2019-01-23T23:59:17Z")

</div>

> [@CTMacUser](#):
>
> - `Type 'AnySequence<Base.Element>' does not conform to protocol 'Collection'`

The default subsequence is `AnySequence<Base.Element>`. Maybe try defining it as `Slice<Base.Element>`.

You might want to look into the standard library's implementation then.

---

<div class="post-metadata">

**Author:** ![CTMacUser](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/ctmacuser/32/1802_2.png) [@CTMacUser](https://forums.swift.org/u/CTMacUser)\
**Post date:** [January 26, 2019, 3:21am UTC](https://forums.swift.org/t/transitioning-a-lazy-sequence-to-a-collection/19685/3 "2019-01-26T03:21:19Z")

</div>

Well, I tried following [an example](https://github.com/apple/swift/blob/master/stdlib/public/core/Filter.swift) at the Swift GitHub:

```
public struct LazyFilterAdjacentValuesSequence<Base: Sequence> {
    let base: Base
    let areEquivalent: (Base.Element, Base.Element) -> Bool
}

extension LazyFilterAdjacentValuesSequence: Sequence {
    //public typealias SubSequence = AnySequence<Base.Element>
    public func makeIterator() -> LazyFilterAdjacentValuesIterator<Base.Iterator> {
        return LazyFilterAdjacentValuesIterator(base.makeIterator(), by: areEquivalent)
    }
    public var underestimatedCount: Int { return base.underestimatedCount.signum() }
}

extension LazyFilterAdjacentValuesSequence: LazySequenceProtocol {}

public typealias LazyFilterAdjacentValuesCollection<T: Collection> = LazyFilterAdjacentValuesSequence<T>

extension LazyFilterAdjacentValuesCollection: Collection {
    //public typealias Index = Base.Index
    //public typealias SubSequence = LazyFilterAdjacentValuesCollection<Base.SubSequence>
    public var startIndex: Base.Index { return base.startIndex }
    public var endIndex: Base.Index { return base.endIndex }
    public subscript(position: Base.Index) -> Base.Element { return base[position] }
    public subscript(bounds: Range<Base.Index>) -> LazyFilterAdjacentValuesCollection<Base.SubSequence> {
        return LazyFilterAdjacentValuesCollection(base: base[bounds], areEquivalent: areEquivalent)
    }
    public func index(after i: Base.Index) -> Base.Index {
        return base[base.index(after: i)...].firstIndex(where: { !areEquivalent(base[i], $0) }) ?? endIndex
    }
}

```

There are two errors on the line defining the extension for `Collection`:

- `Type 'AnySequence<Base.Element>' does not conform to protocol 'Collection'`
- `Type 'LazyFilterAdjacentValuesSequence<Base>' does not conform to protocol 'Collection'`

I'm using Xcode 10.1, which I think comes with Swift 4.2.1. The current Swift system at GitHub is set for a Swift 5.0 beta, I think. I think a big blocker is that `SubSequence` is locked to `AnySequence` in the `Sequence` extension and I have to completely redo it for the `Collection` extension, and Swift won't allow the override. This isn't a problem in Swift 5 because S5 rips out `Sequence.SubSequence`, so its `Collection.SubSequence` has no conflicts.

1. Can anyone check that this code works for Swift 5?
2. Is there a workaround for Swift 4.2? Or do I have to wait for S5?
