Kotlin – How to pass a function as parameter

Recently, I’ve noticed that there are a few different ways to pass a function as parameter in Kotlin. In this post I will use 2 functions: sum and divide. We have to declare the sum function, in such way that it can receive the divide function as argument.

The most common and often more convenient (according to Kotlin documentation) is to pass a lambda expression.

1. Pass a lambda expression

In order to make the sum function to accept a function passed as lambda expression, we have to declare the 3rd parameter c as a lambda.

lambda expression with no parameters

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val sum = sum(6, 3, { divide(6, 3) }) // returns 11
        Log.e("SUM", sum.toString())
    }

    private fun sum(a: Int, b: Int, c: () -> Int): Int {
        return a + b + c()
    }

    private fun divide(a: Int, b: Int): Int {
        return a / b
    }
}

lambda expression with 2 parameters

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        val sum = sum(6, 3, { a, b -> divide(a, b) }) // returns 11
        Log.e("SUM", sum.toString())
    }
    
    private fun sum(a: Int, b: Int, c: (Int, Int) -> Int): Int {
        return a + b + c(a, b)
    }
    
    private fun divide(a: Int, b: Int): Int {
        return a / b
    }
}

pass lambda expression directly without divide method

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val sum = sum(6, 3, { a, b -> a / b }) // returns 11
        Log.e("SUM", sum.toString())
    }

    private fun sum(a: Int, b: Int, c: (Int, Int) -> Int): Int {
        return a + b + c(a, b)
    }
}

2. Use :: operator

class MainActivity : AppCompatActivity() {

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

        val sum = sum(6, 3, (this::divide)(6,3))// returns 11
        Log.e("SUM", sum.toString())
    }

    private fun sum(a: Int, b: Int, c: Int): Int {
        return a + b + c
    }
    
    private fun divide(a: Int, b: Int): Int {
        return a / b
    }
}

As you can see, the signature for the 3rd param from sum function also changed. As we do not pass a function as lambda, we declare the c parameter as a “normal” Int.

Also, notice how we had to reference the divide function in this case. We had to specify the context (the class in which the function was declared), and the arguments were declared separately inside other parenthesis.

(this::divide)(6,3)

Specifying the context was necessary because the functions are declared in a class. Only if we write the functions directly in a Kotlin file (NOT inside a class) we can call directly ::divide. See the example below:

Exit mobile version