addzo
addzo

Reputation: 867

Kotlin Syntax Intended Meaning

This is not a question about how to do this but a question about the reasoning behind it. I have scoured SO, the Kotlin docs and the googs to find WHY the Kotlin people did their syntax this way but can't really understand it. So I'm hoping that someone brilliant here can help me.

Given:

private fun printResult(function: (Int, Int) -> Int, a: Int, b: Int) {

I get that:

"function: (Int, Int)" 

means that this is a function we are passing in and its signature takes two Int parameters.

Further, I get that:

"-> Int" 

means that this function returns an Int

And lastly, I get that:

"a: Int, b: Int" 

is the normal arguments/parameters list, and this is where we receive the actual parameters.

But it seem clunky to me.

Why go to the trouble of giving the signature:

"(Int, Int) -> Int"

and then insist on repeating the arguments again:

"a: Int, b: Int"

But if you have to do that, ok, but why don't you repeat the return for clarity'd sake so that it's something like:

"private fun printResult(function: (Int, Int) -> Int, a: Int, b: Int): Int"

Or even:

"private fun printResult(function: (a: Int, b: Int) -> Int) {"

It seems like unclear syntax with repeats that don't need to be there and/or the potential for unclear signatures as your functions get more complicated.

What am I missing?

Thanks


Example after Forpas and Abib's explanation - for clarity for anyone thinking like I do:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    printResult(::add, 4, 2)
    printResult(::subtract, 4, 2)
}

private fun add(a: Int, b: Int): Int {
    return a + b
}

private fun subtract(a: Int, b: Int): Int {
    return a - b
}

private fun printResult(passedInFunction: (someInt: Int, anotherInt: Int) -> Int, a: Int, b: Int) {
    // Simply takes the values of "a" and "b" and does whatever 
    // the latest version of the "passedInFunction" is set up to do.
    // It does this by passing the arguments that were given to
    // "printResult" into whatever the current version of "passedInFunction" is.
    val result = passedInFunction(a, b)
    println("result: $result")

    // Manipulates the values from the arguments passed into
    // "printResult" and passes the result into "passedInFunction" 
    // as parameters/arguments.
    println("function: " + passedInFunction(a - b, a + b))
}

Upvotes: 0

Views: 194

Answers (2)

forpas
forpas

Reputation: 164069

Let's say that this is the printResult function:

fun printResult(function: (Int, Int) -> Int, a: Int, b: Int) {
    println(function(a - b, a + b))
}

and we also define the multiply function that has the signature of the argument function of printResult:

fun multiply(x: Int, y: Int) = x * y

Now you can call printResult like this:

printResult(this::multiply, 5, 3)

and it will print:

16

You can see that the arguments a and b of printResult are not the arguments of function.
As a matter of fact they would not even be used at all not even for calculations for the arguments of function.
So there is no case of:
unclear syntax with repeats that don't need to be there and/or the potential for unclear signatures

Upvotes: 1

Adib Faramarzi
Adib Faramarzi

Reputation: 4054

The a and b are the arguments of the printResult function, not the function that is in the argument. So printResult takes 3 arguments, a function, a, and b, so whoever designed this function decided that it needs 2 parameters (a and b) and a function that transforms two Ints into another Int.

On another note (as a general tip), arguments of the lambdas can be named too, so printResult(function: (someInt:Int, anotherInt:Int)->Int, a:Int, b:Int) is also valid (It also helps with the IDE code completion when using this function)

Also on a side-note, as per Kotlin docs, It is better to put the lambda/function arguments as the last one ( so the above example becomes private fun printResult(a: Int, b: Int, function: (Int, Int) -> Int) ) because in this case, it can be used like so:

printResult(1,2) { firstInt, secondInt -> ///

Upvotes: 3

Related Questions