Kotlin: how to pass a function as parameter to another?
KotlinKotlin Problem Overview
Given function foo :
fun foo(m: String, bar: (m: String) -> Unit) {
bar(m)
}
We can do:
foo("a message", { println("this is a message: $it") } )
//or
foo("a message") { println("this is a message: $it") }
Now, lets say we have the following function:
fun buz(m: String) {
println("another message: $m")
}
Is there a way I can pass "buz" as a parameter to "foo" ? Something like:
foo("a message", buz)
Kotlin Solutions
Solution 1 - Kotlin
Use ::
to signify a function reference, and then:
fun foo(msg: String, bar: (input: String) -> Unit) {
bar(msg)
}
// my function to pass into the other
fun buz(input: String) {
println("another message: $input")
}
// someone passing buz into foo
fun something() {
foo("hi", ::buz)
}
Since Kotlin 1.1 you can now use functions that are class members ("Bound Callable References"), by prefixing the function reference operator with the instance:
foo("hi", OtherClass()::buz)
foo("hi", thatOtherThing::buz)
foo("hi", this::buz)
Solution 2 - Kotlin
About the member function as parameter:
- Kotlin class doesn't support static member function, so the member function can't be invoked like: Operator::add(5, 4)
- Therefore, the member function can't be used as same as the First-class function.
- A useful approach is to wrap the function with a lambda. It isn't elegant but at least it is working.
code:
class Operator {
fun add(a: Int, b: Int) = a + b
fun inc(a: Int) = a + 1
}
fun calc(a: Int, b: Int, opr: (Int, Int) -> Int) = opr(a, b)
fun calc(a: Int, opr: (Int) -> Int) = opr(a)
fun main(args: Array<String>) {
calc(1, 2, { a, b -> Operator().add(a, b) })
calc(1, { Operator().inc(it) })
}
Solution 3 - Kotlin
Just use "::" before method name
fun foo(function: () -> (Unit)) {
function()
}
fun bar() {
println("Hello World")
}
foo(::bar)
Output : Hello World
Solution 4 - Kotlin
Kotlin 1.1
use ::
to reference method.
like
foo(::buz) // calling buz here
fun buz() {
println("i am called")
}
Solution 5 - Kotlin
If you want to pass setter and getter methods.
private fun setData(setValue: (Int) -> Unit, getValue: () -> (Int)) {
val oldValue = getValue()
val newValue = oldValue * 2
setValue(newValue)
}
Usage:
private var width: Int = 1
setData({ width = it }, { width })
Solution 6 - Kotlin
Jason Minard's answer is a good one. This could also be achieved using a lambda
.
fun foo(m: String, bar: (m: String) -> Unit) {
bar(m)
}
val buz = { m: String ->
println("another message: $m")
}
Which can be called with foo("a message", buz)
.
You can also make this a bit more DRY by using a typealias
.
typealias qux = (m: String) -> Unit
fun foo(m: String, bar: qux) {
bar(m)
}
val buz: qux = { m ->
println("another message: $m")
}
Solution 7 - Kotlin
Here is simple example where I pass the multiplication function as parameter to another function.
fun main(){
result(10,3,::multiplication)// pass function as parameter wow kotlin amazing
}
fun multiplication(first:Int,second:Int):Int{
return first*second
}
fun result(firstOne:Int,secondOne: Int,fn:(Int,Int)->Int){
val result=fn(firstOne,secondOne)
print(result)
}
Solution 8 - Kotlin
apparently this is not supported yet.
more info:
Solution 9 - Kotlin
You can also do this inline using a lambda if that is the only place you are using that function
fun foo(m: String, bar: (m: String) -> Unit) {
bar(m)
}
foo("a message") {
m: String -> println("another message: $m")
}
//Outputs: another message: a message
Solution 10 - Kotlin
Another example:
fun foo(x:Int, Multiply: (Int) -> (Int)) {
println(Multiply(x))
}
fun bar(x:Int):Int{
return x * x
}
foo(10, ::bar)
Solution 11 - Kotlin
First-class functions are currently not supported in Kotlin. There's been debate about whether this would be a good feature to add. I personally think they should.