Skip to content

Instantly share code, notes, and snippets.

@realdadfish
Created November 11, 2021 11:58
Show Gist options
  • Save realdadfish/ba3fc9ec49210a08dcd2c2700fd22a9f to your computer and use it in GitHub Desktop.
Save realdadfish/ba3fc9ec49210a08dcd2c2700fd22a9f to your computer and use it in GitHub Desktop.
A trial to mimic "Type-driven design in Rust" (https://www.youtube.com/watch?v=bnnacleqg6k) with Kotlin
@file:Suppress("EXPERIMENTAL_API_USAGE", "EXPERIMENTAL_UNSIGNED_LITERALS")
interface ExactSizeIterator<T> : Iterator<T> {
val length: UInt
}
fun <T> Collection<T>.exactSizeIterator() = object : ExactSizeIterator<T> {
private val inner = iterator()
override val length: UInt = size.toUInt()
override fun hasNext(): Boolean = inner.hasNext()
override fun next(): T = inner.next()
}
sealed class Bounding {
object Unbounded : Bounding()
data class Bounded(val bound: UInt, val brackets: Pair<Char, Char>) : Bounding()
fun display(current: UInt) {
print("\\u001b[2K")
when (this) {
Unbounded -> print("*")
is Bounded -> {
print(brackets.first)
print("*".repeat(current.toInt()))
print(" ".repeat((bound - current).toInt()))
print(brackets.second)
}
}
}
}
class ProgressIter<I, T : Iterator<I>, B : Bounding>(internal val iterator: T, internal val bounding: B) :
Iterator<I> {
private var current: UInt = 1u
override fun hasNext(): Boolean = iterator.hasNext()
override fun next(): I {
bounding.display(current++)
return iterator.next()
}
}
fun <I> Sequence<I>.progressIterator(): ProgressIter<I, out Iterator<I>, Bounding.Unbounded> =
ProgressIter(iterator(), Bounding.Unbounded)
fun <I> Iterable<I>.progressIterator(): ProgressIter<I, out Iterator<I>, Bounding.Unbounded> =
when (this) {
is Collection<I> -> ProgressIter(exactSizeIterator(), Bounding.Unbounded)
else -> ProgressIter(iterator(), Bounding.Unbounded)
}
fun <I> ProgressIter<I, out Iterator<I>, Bounding.Unbounded>.withBound(): ProgressIter<I, ExactSizeIterator<I>, Bounding.Bounded> =
when (iterator) {
is ExactSizeIterator<I> -> ProgressIter(iterator, Bounding.Bounded(iterator.length, Pair('[', ']')))
else -> error("no ExactSizeIterator")
}
fun <I> ProgressIter<I, ExactSizeIterator<I>, Bounding.Bounded>.withBrackets(brackets: Pair<Char, Char>): ProgressIter<I, ExactSizeIterator<I>, Bounding.Bounded> =
ProgressIter(iterator, bounding.copy(brackets = brackets))
fun main() {
//val seq = generateSequence(1, Int::inc)
val seq = listOf(1, 2, 3, 4)
fun work(item: Int) {
Thread.sleep(1000)
}
for (i in seq.progressIterator().withBound().withBrackets(Pair('<', '>'))) {
work(i)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment