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?
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.
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.
Kotlin with. Like apply , with is used to change instance properties without the need to call dot operator over the reference every time.
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.
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) } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With