Reputation: 15919
I'm facing a compile error when trying to use lambdas / function references with kotlin:
class Foo {
fun getFilteredList(){
val numbers = listOf(1, 2, 3)
numbers.filter(::isOdd) // prints [1, 3]
}
fun isOdd(x: Int): Boolean = x % 2 != 0
}
But I get a compile time error saying a type mismatch:
Error:(18, 16) Gradle: Type inference failed: inline fun kotlin.Iterable.filter(predicate: (T) -> kotlin.Boolean): kotlin.List cannot be applied to receiver: kotlin.List arguments: (kotlin.reflect.KFunction2) Error:(18, 23) Gradle: Type mismatch: inferred type is kotlin.reflect.KFunction2 but (kotlin.Int) -> ??? was expected Error:(18, 23) Gradle: Type mismatch: inferred type is kotlin.reflect.KFunction2 but (kotlin.Int) -> kotlin.Boolean was expected Error:(18, 25) Gradle: Left-hand side of a callable reference with a receiver parameter cannot be empty. Please specify the type of the receiver before '::' explicitly
I'm not sure what the error is nor what type I should specify explicitly before '::'
Another question: Can I use another objects function as reference in kotlin? Something like this:
class Bar {
fun isOdd(x: Int): Boolean = x % 2 != 0
}
class Foo {
fun getFilteredList(){
val bar = Bar()
val numbers = listOf(1, 2, 3)
numbers.filter(bar::isOdd) // Use Bar's method
}
}
Upvotes: 14
Views: 7720
Reputation: 32776
On the second example: yes, the bound function reference syntax is supported since Kotlin 1.1, so you can write bar::isOdd
similarly to Java.
In the first example, the error is trying to say that isOdd
is in fact a function of two parameters (of types Foo
and Int
), and passing a function taking two parameters as an argument whose type is function of one parameter is not allowed. To make the example compile, you can make isOdd
a top-level or a local function, which would make it a function of one parameter of type Int
. Or, if you use Kotlin 1.1+, use the bound function reference syntax and simply write this::isOdd
.
Upvotes: 18
Reputation: 33749
That's funny. "Java strikes back". Haha
Your problem is simple: you declared isOdd
in class Foo
, right? Then it is not a function, but a method. Which means that it requires an instance of Foo
to be passed in (the this
reference) - that's why it is a function of 2 parameters: Foo.(Int) -> Boolean
. And the syntax error shows that - a reference to a method looks like Foo::isOdd
.
Anyway, declaring a non-static method which does not use the object is an antipattern even in Java, don't you agree?
The problem might be solved by declaring a free function without a class or by making it an extension: fun Int.isOdd()
P.S. Regarding your second question - that feature is not supported yet.
Upvotes: 7