Home > database >  How to chain lambdas to a resulting lambda in Kotlin?
How to chain lambdas to a resulting lambda in Kotlin?

Time:10-04

... or the equivalent of java.util.Function.andThen()

In Java

Function<String, String> add1 = string -> string   "1";
Function<String, String> add2 = string -> string   "2";

void print(String string) {
    System.out.println(add1.andThen(add2).apply(string));
}

This function prints string "12"

How would I write it in Kotlin?

val add1 = { string:String -> string   "1" }
val add2 = { string:String -> string   "2" }

fun print(string: String) {
    println(???)
}

CodePudding user response:

The feature you're looking for is called function composition. As far as I can tell, it doesn't come built-in to Kotlin (would love to be corrected on this). But it's very easy to write as an extension function.

infix fun<A, B, C> ((B) -> C).compose(that: (A) -> B): (A) -> C =
  { this(that(it)) }

Now we can write

val add1 = { string:String -> string   "1" }
val add2 = { string:String -> string   "2" }

println((add2 compose add1)("3")) // Prints "312"

I write compose to use right-to-left composition, more in line with the way mathematical functions work.

CodePudding user response:

Granted, this is not exactly what you're looking for, because you can't store a composed function this way in a variable, but you can chain the results of functions using run if the functions themselves don't have the parameter as a receiver:

fun print(string: String) {
    println(add1(string).run(add2))
}

// or

fun print(string: String) {
    println(string.run(add1).run(add2))
}

Since run is an inline function, it doesn't add a wrapper object around each function.

The let function will have the exact same effect. This is because when you pass something other than a lambda to a higher order function, it doesn't matter if the first parameter is a receiver or not. They are treated as the same signature.

  • Related