Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

vararg parameter in a Kotlin lambda

Tags:

lambda

kotlin

I'd like to define a function f() as follows (just an example) :

val f: (vararg strings: String) -> Unit = { for (str in it) println(str) } 

so that I could invoke it with f("a","b","c"). For the above definition of f() I get the compilation error, pointing at the vararg modifier (Kotlin v. 1.3.60 ) :

Unsupported [modifier on parameter in function type] 

How can I define a lambda that accepts a vararg parameter ?

like image 730
David Soroko Avatar asked Dec 31 '17 21:12

David Soroko


People also ask

How do you pass parameters in Kotlin?

You can pass a variable number of arguments to a function by declaring the function with a vararg parameter. In Kotlin, a vararg parameter of type T is internally represented as an array of type T ( Array<T> ) inside the function body.

What does Vararg mean in Kotlin?

Kotlin Android. Sometimes we need a function where we can pass n number of parameters, and the value of n can be decided at runtime. Kotlin provides us to achieve the same by defining a parameter of a function as vararg .

How do you pass lambda as parameter Kotlin?

In Kotlin, a function which can accept a function as parameter or can return a function is called Higher-Order function. Instead of Integer, String or Array as a parameter to function, we will pass anonymous function or lambdas. Frequently, lambdas are passed as parameter in Kotlin functions for the convenience.


2 Answers

I'm afraid this is not possible. The following demonstrates the type of a function with vararg. A vararg parameter is represented by an Array:

fun withVarargs(vararg x: String) = Unit  val f: KFunction1<Array<out String>, Unit> = ::withVarargs 

This behavior is also suggested in the docs:

Inside a function a vararg-parameter of type T is visible as an array of T, i.e. the ts variable in the example above has type Array<out T>.

So you had to use an Array<String> in your example. Instead of writing your function as a lambda, you may use an ordinary function that allows to use vararg and make the call look as desired:

fun f(vararg strings: String) = strings.forEach(::println)  f("a","b","c") 
like image 174
s1m0nw1 Avatar answered Sep 21 '22 16:09

s1m0nw1


If you need a function pointer (to be passed as an argument). It can be achieved with a workaround (hack):

fun f(vararg strings: String): Unit = strings.forEach(::println)   val fWrapper:(Array<String>)-> Unit = {arr:Array<String>->f(*arr)} 
like image 25
Komdosh Avatar answered Sep 20 '22 16:09

Komdosh