Extensions for Kotlin sequences
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

  1. package moe.kageru.sekwences
  2. /**
  3. * Sequence that holds a [CoalescingIterator].
  4. */
  5. internal class CoalescingSequence<T>(private val source: Sequence<T>, private inline val merger: (T, T) -> T?) : Sequence<T> {
  6. override fun iterator(): Iterator<T> {
  7. return CoalescingIterator(source.iterator(), merger)
  8. }
  9. /**
  10. * Iterator that will attempt to merge adjacent elements as described in the KDoc for [coalesce].
  11. */
  12. internal class CoalescingIterator<T>(private val source: Iterator<T>, private inline val merger: (T, T) -> T?) : Iterator<T> {
  13. private var previous: T = if (source.hasNext()) source.next() else error("Please don’t pass empty iterators in here")
  14. // The reason we need this marker is that our iterator can still hold one value, even if the source has been drained.
  15. private var hasNext = true
  16. override fun hasNext() = hasNext
  17. override tailrec fun next(): T {
  18. if (!source.hasNext()) {
  19. hasNext = false
  20. return previous
  21. }
  22. val current = source.next()
  23. val merged = merger(previous, current)
  24. // If the elements can’t be merged, return the first, then save the second for next time.
  25. return if (merged == null) {
  26. val ret = previous
  27. previous = current
  28. ret
  29. } else {
  30. previous = merged
  31. next()
  32. }
  33. }
  34. }
  35. }