Skip to content

Instantly share code, notes, and snippets.

@JadenGeller
Created October 20, 2023 19:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JadenGeller/48f5219ff35a03dfb57c8497a494ba97 to your computer and use it in GitHub Desktop.
Save JadenGeller/48f5219ff35a03dfb57c8497a494ba97 to your computer and use it in GitHub Desktop.
like scan from Haskell
struct ScanSequence<Base: Sequence, Result>: Sequence {
let base: Base
let first: Result
let next: (Result, Base.Element) -> Result
func makeIterator() -> PrependIterator<ScanIterator<Base.Iterator, Result>> {
.init(base: .init(base: base.makeIterator(), previous: first, combine: next), first: first)
}
}
extension Sequence {
func scan<Result>(_ first: Result, _ next: @escaping (Result, Element) -> Result) -> ScanSequence<Self, Result> {
return ScanSequence(base: self, first: first, next: next)
}
}
struct PrependIterator<Base: IteratorProtocol>: IteratorProtocol {
var base: Base
var first: Base.Element?
mutating func next() -> Base.Element? {
if let first {
self.first = nil
return first
} else {
return base.next()
}
}
}
struct ScanIterator<Base: IteratorProtocol, Result>: IteratorProtocol {
var base: Base
var previous: Result
let combine: (Result, Base.Element) -> Result
mutating func next() -> Result? {
guard let next = base.next() else { return nil }
previous = combine(previous, next)
return previous
}
}
@JadenGeller
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment