Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simpler or more functional way of chaining objects in Kotlin

Tags:

kotlin

I have created a helper method buildChain which essentially creates a chain of objects given that they implement the interface IChain<T> and set the contracts next member

The Code

interface Chain<T> {
    var next: T?

    operator fun plus(next: T): T?
}

fun <T : Chain<T>> buildChain(first: T, vararg members: T): T {
    var next: T? = null
    members.forEachIndexed { i, t ->
        if (i == 0) {
            next = first + t
        } else {
            next = next?.run { this + t }
        }
    }
    return first
}

Implementation example

data class Person(val name: String) : Chain<Person> {
    override var next: Person? = null

    override fun plus(next: Person): Person? {
        this.next = next
        return next
    }
}

fun createPersonChain()
        = buildChain(Person("Bob"), Person("Bitzy"), Person("Blitzy"))

Implementaion output example

@JvmStatic fun main(args: Array<String>) {
    var first = createPersonChain()
    // first.name = "Bob"
    // first.next.name = "Bitzy"
    // first.next.next.name = "Blitzy"
 }

Is there a functional or simpler way for acheiving the code above keeping the implementaion usage the same?

like image 487
Kevin Crain Avatar asked Mar 05 '16 17:03

Kevin Crain


People also ask

How do you chain a function in Kotlin?

To use the chain, we'll use Kotlin's extending functions and leverage the then() function to chain our function calls. Each extension function calls the linking then function from the Chain to build LinkedChain objects composing our final Car.

How do you return a function in Kotlin?

To return values, we use the return keyword. In the example, we have two square functions. When a funcion has a body enclosed by curly brackets, it returns a value using the return keyword. The return keyword is not used for functions with expression bodies.

What is with in Kotlin?

Kotlin with. Like apply , with is used to change instance properties without the need to call dot operator over the reference every time.

What is function chaining in JavaScript?

Function chaining is a pattern in JavaScript where multiple functions are called on the same object consecutively. Using the same object reference, multiple functions can be invoked. It increases the readability of the code and means less redundancy.


1 Answers

A functional idiom fold suits your needs well: it takes an initial item and then iterates over the other items, maintaining an accumulated value, which is updated on each item being processed with the function you provide.

In Kotlin, it is fold extension function for Iterable, Sequence or Array.

You can use it in the following way:

fun <T : Chain<T>> buildChain(first: T, vararg members: T): T {
    members.fold(first as T?) { acc, i -> acc?.let { it + i } }
    return first
}

Here first as T? cast is needed for the accumulator type to be inferred as nullable T?, because plus in your Chain<T> returns nullable value (by the way, is it necessary?).

You can also use foldRight, which just iterates in the opposite order:

fun <T : Chain<T>> buildChain(first: T, vararg members: T): T? =
        (listOf(first) + members)
            .foldRight(null as T?) { i, acc -> acc?.let { i + acc }; i }

And there are reduce and reduceRight with similar semantics but using the first and the last item respectively for the accumulator's initial value. Here's the example with reduceRight:

fun <T : Chain<T>> buildChain(first: T, vararg members: T): T? =
        (listOf(first) + members).reduceRight { i, acc -> i.apply { plus(acc) } }
like image 168
hotkey Avatar answered Dec 01 '22 19:12

hotkey