Reputation: 40500
I have two extension functions declared in Kotin (1.3):
fun SomeClass.fooBuilder(vararg x: String, fn: ((String) -> Unit)? = null): Result.Builder = TODO()
fun SomeClass.foo(vararg x: String, fn: ((String) -> Unit)? = null): Result = fooBuilder(*x, fn).build()
What I want to do is to call fooBuilder
from foo
and simply call build()
on the result returned from fooBuilder
.
Unfortunately the code above doesn't compile since the call to fooBuilder(*x, fn).build()
fails with:
Error:(28, 143) Kotlin: Type mismatch: inferred type is ((String) -> Unit)? but String was expected
I.e. the compiler seem to think that I want to pass additional string (x
) arguments but what I actually want to pass is the function.
How can I resolve this and while retaining the option to use to omit the parentheses when specifying fn
as in this example:
SomeClass().foo("x") { str -> println("Hello $str") }
Upvotes: 0
Views: 3938
Reputation: 18547
Here's another option — it's not as clear, short, or efficient as using a named param, but I include it for completeness.
It's to pass fn
outside the parens, just like the caller has to do. I don't think you can do that directly, but you can wrap the call to fn
like this:
fun SomeClass.foo(vararg x: String, fn: ((String) -> Unit)? = null): Result
= fooBuilder(*x){ fn?.invoke(it) }.build()
Upvotes: 0
Reputation: 4753
You have two options:
1) vararg should be last argument (but then you won't be able to use simplified lambda call)
2) use named params:
fun SomeClass.fooBuilder(vararg x: String, fn: ((String) -> Unit)? = null): Result.Builder = TODO()
fun SomeClass.foo(vararg x: String, fn: ((String) -> Unit)? = null): Result = fooBuilder(x = *x, fn = fn).build()
Error you got is very logical - how compiler can know when passing vararg argumnets is finished?
Upvotes: 1
Reputation: 986
Any parameters that come after vararg
have to be passed as a named parameter. Try it:
fun SomeClass.fooBuilder(vararg x: String, fn: ((String) -> Unit)? = null): Result.Builder = TODO()
fun SomeClass.foo(vararg x: String, fn: ((String) -> Unit)? = null): Result = fooBuilder(*x, fn = fn).build() // here I used named param
// it should work now:
SomeClass().foo("x") { str -> println("Hello $str") }
Upvotes: 2