You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
41 lines
1.5 KiB
41 lines
1.5 KiB
package moe.kageru.sekwences |
|
|
|
|
|
/** |
|
* Sequence that holds a [CoalescingIterator]. |
|
*/ |
|
internal class CoalescingSequence<T>(private val source: Sequence<T>, private inline val merger: (T, T) -> T?) : Sequence<T> { |
|
override fun iterator(): Iterator<T> { |
|
return CoalescingIterator(source.iterator(), merger) |
|
} |
|
|
|
/** |
|
* Iterator that will attempt to merge adjacent elements as described in the KDoc for [coalesce]. |
|
*/ |
|
internal class CoalescingIterator<T>(private val source: Iterator<T>, private inline val merger: (T, T) -> T?) : Iterator<T> { |
|
private var previous: T = if (source.hasNext()) source.next() else error("Please don’t pass empty iterators in here") |
|
// The reason we need this marker is that our iterator can still hold one value, even if the source has been drained. |
|
private var hasNext = true |
|
|
|
override fun hasNext() = hasNext |
|
|
|
override tailrec fun next(): T { |
|
if (!source.hasNext()) { |
|
hasNext = false |
|
return previous |
|
} |
|
|
|
val current = source.next() |
|
val merged = merger(previous, current) |
|
// If the elements can’t be merged, return the first, then save the second for next time. |
|
return if (merged == null) { |
|
val ret = previous |
|
previous = current |
|
ret |
|
} else { |
|
previous = merged |
|
next() |
|
} |
|
} |
|
} |
|
} |