Reputation: 1534
I can write lambdas id_Int
and id_Boolean
with explicit type. And I can write function identity
with type parameter. Can I write lambdas with type parameter?
fun testFuncInt(f: (Int) -> Int): Int = f(1) + 2
val id_Int = { x: Int -> x }
fun testFuncBoolean(f: (Boolean) -> Boolean): Boolean = !f(false)
val id_Boolean = { x: Boolean -> x }
fun <T> identity(x: T) = x
fun main(args: Array<String>) {
println(testFuncInt(id_Int))
println(testFuncInt(::identity))
println(testFuncBoolean(id_Boolean))
println(testFuncBoolean(::identity))
}
Upvotes: 22
Views: 14226
Reputation: 280
No, but you generally don't need to. A lambda has no declaration (which is kind of the point), so it's essentially an expression you can pass to a function, store in a val
/var
as you did when doing
val id_Boolean = { x: Boolean -> x }
but the type really gets worked out as it would in an expression.
The calls here will resolve to the correct type, since your functions takes a function that takes an Int
and returns an Int
, and a function that takes a Boolean
and returns a Boolean
testFuncInt({ x -> x }) // x is an Int
testFuncInt({ it }) // it is the default argument
testFuncInt { x -> x } // as top one, Kotlin's syntactic sugar
The important thing here is that the lambda expression still offers type safety, i.e. if you did something like this
fun <T> foo(x: T, lambda: (T) -> Boolean): Boolean = lambda(x)
foo(42, { x -> x }) // oops, lambda takes a T and returns a T
this will trigger a compiler error as lambda
's types don't match what foo
expects, i.e. foo
will pass an Int
to the lambda and it expects a Boolean
back. On the other hand, if you do this
foo(123, { it == 42 })
foo(123) { it == 42 } // equivalent to above
The return type is actually deduced to be a Boolean
as that's what the result of a comparison operation evaluates to and as 123 and 42 are of the same type, lambda
's types actually fit into what foo
expects.
Upvotes: 2
Reputation: 2221
Kotlin does not have support for declaring generic properties without declaring that type at class level (see also), but you can do it using a function that returns a lambda corresponding to the desired type:
fun main(args: Array<String>) {
println(testFuncBoolean(id()))
println(testFuncInt(id()))
}
fun <T> id(): (T) -> T = { it }
fun testFuncInt(f: (Int) -> Int): Int = f(1) + 2
fun testFuncBoolean(f: (Boolean) -> Boolean): Boolean = !f(false)
Upvotes: 14
Reputation: 17809
You can not write lambda with generics, why following paragraph taken from official documentation says it all.
A lambda expression or an anonymous function is a "function literal", i.e. a function that is not declared, but passed immediately as an expression
A lambda expression or function is not declared, its an anonymous function.
But ultimately we do same thing by declaring function type as generic. We can pass a lambda expression that does the job.
fun testFuncInt(f: (Int) -> Int): Int = f(1) + 2
you can call it like: testFuncInt{ a -> a }
or testFuncInt{ it }
So finally you are doing same thing (lambdas with type parameter), but there is no term like that as lambdas are expressions or anonymous functions.
Hope it helps.
Upvotes: 2