Search code examples
kotlinrx-java

Kotlin quadruple, quintuple, etc. for destructuring


I am looking for a clean way to create destructurable objects in-line. kotlin.Pair and kotlin.Triple cover a lot of use cases, but sometimes there are more objects that are needed to be passed.

One sample use case is RX's zip function, where the results of several I/O calls need to be mapped into another object:

Single
    .zip(repositoryA.loadData(someId),
         repositoryB.loadData(someId),
         repositoryC.loadAll(),
         repositoryD.loadAll()),
         { objectA, objectB, objectsC, objectsD -> /*some Kotlin magic*/ }
    )
    .map { (objectA, objectB, objectsC, objectsD) -> /*do the mapping*/ }

I am trying to figure out what would go in the "some Kotlin magic" part. If there were only 3 repositories, it would be

Triple(objectA, objectB, objectsC)

Do I need to create a new data class for this, and for any n-tuple case, or is there another way?


Solution

  • Basics

    Let's see how destructuring works:

    Kotlin defines a convention for this, i.e. componentX() operator functions are an example of the principle of conventions used in Kotlin in many places. These componentX() functions are used by the compiler for the initialization of variables in destructuring declarations.

    For example in Pair<A,B> these functions look as follows:

    operator fun component1(): A = first 
    
    operator fun component2(): B = second
    

    As you can see these are operators, specially handled functions. These componentX() functions can be provided by the developer and will automatically be produced by the compiler for data classes. Pair also is such a data class btw.

    Answer

    Thus, just go ahead and use data classes whenever you need more than a Triple.

    For example, a class MultiComponent defined as this:

    data class MultiComponent(val x: Int, val y: Int, val z: Int, val a: Int, val b: Int, val c: Int)
    

    will be compiled to a class with functions component1(), component2(), ..., component6() and can be used in destructuring declarations:

    val (q, w, e, r, t, z) = MultiComponent(1, 2, 3, 4, 5, 6)