Kotlin lambda understanding problem

i am new to kotlin so while understanding lambda in the kotlin higher-order function docs i really can not understand this part :-
{{ To specify that a function type is nullable, use parentheses: ((Int, Int) -> Int)? .

Function types can be combined using parentheses: (Int) -> ((Int) -> Unit)

The arrow notation is right-associative, (Int) -> (Int) -> Unit is equivalent to the previous example, but not to ((Int) -> (Int)) -> Unit }}

what is (Int) → ((Int) → Unit) mean exactly also the last part {(Int) → (Int) → Unit} and {((Int) → (Int)) → Unit} please if any one could help me i will be thankful

(Int) -> ((Int) -> Unit) is a method that, given an Int, produces (Int) -> Unit, a function that, given an Int, gives Unit. It would be used like this, with type specifications for clarity:

fun example(lambda1: (Int) -> ((Int) -> Unit)) {
    val lambda2: (Int) -> Unit = lambda1.invoke(5)
    lambda2.invoke(7)

Meanwhile, ((Int) -> (Int)) -> Unit is a method that takes as an argument an (Int) -> Int, and returns Unit. An example might be a mutation on a boxed value:

data class Box(var value: Int) {
    fun mutate(mutation: ((Int) -> Int) -> Unit) {
        value = mutation(value)
    }
}

For a practical example read above, I try to do it a bit more theoretical.

An approach to decipher difficult lambda’s…

(Two times the same story, but the Java-one is for if you know Java and is not really documented)

If you do understand Java functional interfaces
(Int) -> Unit
// roughly the same as
Consumer<Int>

(Int) -> Int
//roughly the same as
Function<Int, Int>

(Int, Int) -> Int 
//roughly the same as 
BiFunction<Int, Int, Int>

((Int, Int) -> Int)? 
// roughly the same as
(BiFunction<Int, Int, Int>)?
// roughly the same as
BiFunction<Int, Int, Int>? //type with question mark, so nullable.


(Int) -> ((Int) -> Unit)
//roughly the same as
(Int) -> (Consumer<Int>)
//roughly the same as
Function<Int, Consumer<Int>>

((Int) -> (Int)) -> Unit
//roughly the same as
(Function<Int, Int>)-> Unit
//roughly the same as
Consumer<Function<Int, Int>>

(Kotlin doesn’t use the functional interfaces but it’s own, so it’s roughly the same.)

(Int)->Unit //takes an Int, returns Unit
(Int)->Int //takes an int, returns an Int
(Int, Int) ->Unit //takes 2 Integers, returns Unit

In Kotlin we can create typealiases, other names for types.
A lambda is a type, so we can give it another name.
Let’s do it:

typealias IntConsumer = (Int) -> Unit //takes an int, return Unit
typealias IntChanger = (Int) -> Int  //takes an int, returns an Int.
typeAlias IntCombiner = (Int, Int) -> Int //takes two ints, returns an Int

now let’s rewrite your function using our created typealiases:

   ((Int, Int) -> Int)?
/*. |---------------| is our IntCombiner */
    (IntCombiner)?
//which is the same as
    IntCombiner?

In other words, if we have a variable with the type IntCombiner, the variable cannot be null.
If we have a variable with the type IntCombiner? it can be null.
So, it just means it can be either a lambda which takes two Ints and returns one Int, or it can be null.

ok, up to the next

(Int) -> ((Int) -> Unit)
       /* |-----------| is our IntConsumer */
(Int) -> (IntConsumer)
//which is the same as
(Int) -> IntConsumer

This means it takes an Int and returns our IntConsumer.

  ((Int) -> (Int)) -> Unit
/* |------------| is our IntChanger */
   ( IntChanger ) -> Unit

This means it takes our IntChanger and returns Unit

if you rewrite and there are no (), you start rewriting from the right.
This brings us to the last example

 (Int) -> (Int) -> Unit
 // is this 
(Int) -> IntConsumer
// or is it
(IntChanger) -> Unit

If you start rewriting from the right, you come to the answer:

 (Int) -> IntConsumer
 //or written out:
(Int) -> (Int -> Unit)
//or in words, takes an int, returns a lambda that takes an int and returns nothing.
1 Like