package moe.kageru.sekwences /** * Sequence that holds a [CoalescingIterator]. */ internal class CoalescingSequence(private val source: Sequence, private inline val merger: (T, T) -> T?) : Sequence { override fun iterator(): Iterator { return CoalescingIterator(source.iterator(), merger) } /** * Iterator that will attempt to merge adjacent elements as described in the KDoc for [coalesce]. */ internal class CoalescingIterator(private val source: Iterator, private inline val merger: (T, T) -> T?) : Iterator { 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() } } } }