A simplified or more functional way of connecting objects in Kotlin

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

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")) 

Implementation 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 to get the above code value while keeping the implementation using the same?

+5
source share
2 answers

Functional idiom fold meets your needs: it takes the initial element and then iterates over the other elements, maintaining the accumulated value, which is updated for each element being processed using the function that you provide.

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

You can use it as follows:

 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? Is it required that the battery type be deduced as nullable T? , because plus in your Chain<T> returns NULL (by the way, is this necessary?).

You can also use foldRight , which simply foldRight in the reverse 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 is reduce and reduceRight with similar semantics, but using the first and last elements, respectively, for the initial value of the battery. Here is an example with reduceRight :

 fun <T : Chain<T>> buildChain(first: T, vararg members: T): T? = (listOf(first) + members).reduceRight { i, acc -> i.apply { plus(acc) } } 
+8
source

Try apply{} . In the {} block, pass your methods separated by the ';'

 Object().apply{ method1(); signUp(user) } 
0
source

Source: https://habr.com/ru/post/1244493/


All Articles