-
-
Save danielctull/ec521f3fc2aadabb17d38f716e55c5f7 to your computer and use it in GitHub Desktop.
/// A `Collection` that contains the same elements as this one, | |
/// in the reversed order. | |
public protocol ReversedCollectionProtocol: BidirectionalCollection { | |
associatedtype Elements: Collection | |
where Elements.Iterator.Element == Iterator.Element | |
var elements: Elements { get } | |
} | |
extension ReversedCollection: ReversedCollectionProtocol { | |
public var elements: Base { | |
return _base | |
} | |
} | |
extension ReversedCollectionProtocol { | |
// Reversing a reversed collection returns the original collection. | |
public func reversed() -> Elements { | |
return elements | |
} | |
} | |
extension LazyCollectionProtocol | |
where | |
Self: BidirectionalCollection, | |
Elements: ReversedCollectionProtocol { | |
// Reversing a lazy reversed collection returns a lazy representation of the original collection. | |
public func reversed() -> LazyCollection<Elements.Elements> { | |
return elements.elements.lazy | |
} | |
} | |
extension LazyCollectionProtocol | |
where | |
Self: BidirectionalCollection, | |
Elements: BidirectionalCollection { | |
// Reversing a lazy collection returns a lazy representation of | |
// the reversed representation of the original collection. | |
public func reversed() -> LazyCollection<ReversedCollection<Elements>> { | |
return elements.reversed().lazy | |
} | |
} | |
// MARK:- Tests | |
func printtype(_ name: String, _ value: Any) { | |
print("") | |
print(name) | |
print(type(of: value)) | |
} | |
let array = [0,1,3,4] | |
let reversed = array.reversed() | |
let reversedreversed = reversed.reversed() | |
printtype("array:", array) | |
printtype("reversed:", reversed) | |
printtype("reversed reversed:", reversedreversed) | |
print("\n=====") | |
let oldreversedreversed: ReversedCollection<ReversedCollection<[Int]>> = reversed.reversed() | |
printtype("old reversed reversed:", oldreversedreversed) | |
let newreversedreversed: [Int] = reversed.reversed() | |
printtype("new reversed reversed:", newreversedreversed) | |
print("\n=====") | |
let lazy = array.lazy | |
let lazyreversed = lazy.reversed() | |
let lazyreversedreversed = lazyreversed.reversed() | |
printtype("lazy:", lazy) | |
printtype("lazy reversed:", lazyreversed) | |
printtype("lazy reversed reversed:", lazyreversedreversed) | |
print("\n=====") | |
let oldlazyreversedreversed: LazyCollection<ReversedCollection<ReversedCollection<[Int]>>> = lazyreversed.reversed() | |
printtype("old lazy reversed reversed:", oldlazyreversedreversed) | |
let newlazyreversedreversed: LazyCollection<[Int]> = lazyreversed.reversed() | |
printtype("new lazy reversed reversed:", newlazyreversedreversed) | |
print("\n=====") | |
let reversedlazy = reversed.lazy | |
let reversedlazyreversed = reversedlazy.reversed() | |
printtype("lazy:", lazy) | |
printtype("reversed lazy:", reversedlazy) | |
printtype("reversed lazy reversed:", reversedlazyreversed) | |
print("\n=====") | |
let oldreversedlazyreversed: LazyCollection<ReversedCollection<ReversedCollection<[Int]>>> = reversedlazy.reversed() | |
printtype("old reversed lazy reversed:", oldreversedlazyreversed) | |
let newreversedlazyreversed: LazyCollection<[Int]> = reversedlazy.reversed() | |
printtype("new reversed lazy reversed:", newreversedlazyreversed) |
I've tried changing the extension on LazyCollectionProtocol
so that its Elements is ReversedCollection
(to avoid needed this unwanted new ReversedCollectionProtocol
protocol), but it requires the generic type to be specified. I've tried to use BidirectionalCollection
:
extension LazyCollectionProtocol
where
Self: BidirectionalCollection,
Elements == ReversedCollection<BidirectionalCollection>
but I get the error:
using 'BidirectionalCollection' as a concrete type conforming to protocol 'BidirectionalCollection' is not supported
I'm not too sure how else I can constrain this extension. I think ideally it'd be nice to add a new generic into the mix, something like the following:
extension LazyCollectionProtocol
where
Self: BidirectionalCollection,
Elements == ReversedCollection<T> {
// Reversing a lazy reversed collection returns a lazy representation of the original collection.
public func reversed() -> LazyCollection<T> {
return elements._base.lazy
}
}
but unsurprisingly this gives an an error
use of undeclared type 'T'
I've looked through the Language Reference section in the Swift book (for version 4.1) around Extensions and Generic Where Clauses to see if there was anything in the language that I was missing that could help add this constraint, but I can't find anything there.
I tried and failed to constrain
LazyCollectionProtocol
when its elements are aReversedCollection
, but couldn't get that to work with the generics ofReversedCollection
– perhaps it's not possible, and that's the reason the stdlib currently hasLazyCollectionProtocol
to deal withLazyCollection
types?Taking inspiration from this I made a
ReversedCollectionProtocol
to constrain the lazy collection so that it can return a lazy view on the original elements when the elements are already reversed.