Cirkle - A Circularly-addressable List for Kotlin
A Circularly-addressable List and MutableList for Kotlin
Cirkle!
TL;DR: Cirkle is available on GitHub and as always, I appreciate feedback.
There were several times during the Advent of Code 2017
where I really wanted a List
or MutableList
that acted like a circle rather than a line. By that I mean I should be able to address it from the right or the left, kind of like I can in Python. So I went ahead and wrote one in Kotlin, and it was easy thanks to delegates and extension functions.
For instance, suppose I want to address the list from the right:
val cirkle = listOf("a", "b", "c").circular()
// Negative addressing:
cirkle[-1] // "c"
// Overly positive addressing:
cirkle[3] // "a"
This works for anything that can be indexed in List
and MutableList
:
val cirkle = mutableListOf("a", "b", "c").circular()
// Set:
cirkle[-1] = "d" // ["a", "b", "d"]
// SubList:
cirkle.subList(0, -1) // ["a", "b"]
// Add:
cirkle.add(-1, "d") // ["a", "b", "d", "c"]
// etc (listIterator, addAll...)
Go check it out on GitHub if you find this interesting.
Implementation
Thanks to Kotlin’s Delegation
support, implementing this was really easy. First, I created a concrete class that took a List
or MutableList
as an argument, implemented that interface, and delegated to the instance passed in:
// CircularList.kt
class CircularList<out T>(private val list: List<T>) : List<T> by list {
override fun get(index: Int): T =
list[index.safely()]
// Other overrides removed for brevity.
private fun Int.safely(): Int =
if (this < 0) (this % size + size) % size
else this % size
}
I used a similar approach for the MutableCircularList
, and ended up providing extension functions to make creating these more idiomatic:
fun <T> List<T>.circular(): CircularList<T> = CircularList(this)
fun <T> MutableList<T>.circular(): MutableList<T> = MutableCircularList(this)
There are quite a few unit tests to look through, those should give you a complete idea as to Cirkle’s capabilities.
Cirkle is not a large or complicated library, but I had fun making it and I hope somebody out there finds a use for it one day.
Have fun!