Monday, January 1, 2018

Kotlin - Tuple type

It is very simple to write a Tuple type with the expressiveness of Kotlin. My objective expressed in tests is the following:

1. Be able to define a Tuple of up to 5 elements and be able to retrieve the elements using an index like placeholder, in a test expressed with 2 elements like this:

val tup = Tuple("elem1", "elem2")
assertThat(tup._1).isEqualTo("elem1")
assertThat(tup._2).isEqualTo("elem2")

2. Be able to de-construct the constituent types along the following lines:
val tup = Tuple("elem1", "elem2")
val (e1, e2) = tup

assertThat(e1).isEqualTo("elem1")
assertThat(e2).isEqualTo("elem2")


Implementation

The implementation for a tuple of 2 elements is the following in its entirity:

data class Tuple2<out A, out B>(val _1: A, val _2: B)

A Kotlin data class provides all the underlying support of being able to retrieve the individual fields and the ability to destructure using an expression like this:

val (e1, e2) = Tuple2("elem1", "elem2")

All that I need to do at this point is provide a helper that creates a tuple of appropriate size based on the number of arguments provided which I have defined as follows:

object Tuple {
    operator fun <A> invoke(_1: A): Tuple1<A> = Tuple1(_1)
    operator fun <A, B> invoke(_1: A, _2: B): Tuple2<A, B> = Tuple2(_1, _2)
    operator fun <A, B, C> invoke(_1: A, _2: B, _3: C): Tuple3<A, B, C> = Tuple3(_1, _2, _3)
    operator fun <A, B, C, D> invoke(_1: A, _2: B, _3: C, _4: D): Tuple4<A, B, C, D> = Tuple4(_1, _2, _3, _4)
    operator fun <A, B, C, D, E> invoke(_1: A, _2: B, _3: C, _4: D, _5: E): Tuple5<A, B, C, D, E> = Tuple5(_1, _2, _3, _4, _5)
}

which allows me to define tuples of different sizes using a construct which looks like this:

val tup2 = Tuple("elem1", "elem2")
val tup3 = Tuple("elem1", "elem2", "elem3")
val tup4 = Tuple("elem1", "elem2", "elem3", "elem4")

A little more twist, typically a Pair type is an alias for Tuple with 2 elements and Triple is an alias for a Tuple of 3 elements, this can be trivially defined in Kotlin the following way:

typealias Pair<A, B> = Tuple2<A, B>
typealias Triple<A, B, C> = Tuple3<A, B, C>

Simple indeed! a more filled-in sample is available in my github repo here - https://github.com/bijukunjummen/kfun

No comments:

Post a Comment