fun <T> f(): T { return foo.bar<T>() }
This fails because Kotlin wants T to be reified and f inline.
But f is a local function and foo is a local variable outside the scope and you cannot inline a local function: "Local inline functions are not yet supported in inline functions"
This is really annoying as it seems like one cannot transparently pass through a template/type locally.
In my code I'm trying to reduce the complexity of
// Must have reified here to be able to determine the type of T
inline fun <reified T> Long.bar(): T {
return when (T::class) {
Int::class -> 43 as T
Float::class -> 34f as T
else -> throw Exception("")
}
}
fun main() {
var foo = 3L
fun <T> f(): T { return foo.bar<T>() }
f<Int>()
}
ERROR: Cannot use 'T' as reified type parameter. Use a class instead.
The entire point of f
is to localize foo.bar<T>
. (the real code is more complex).
Seems Kotlin's templates are not very sophisticated. Is there any way around this without a lot of trouble? (I could remove the type dependency and pass the type as a value parameter but that removes the type type checking and consistency and all that.
Inline local functions are not a feature in Kotlin, but there is a feature request for it on YouTrack: KT-17579.
As an alternative, you can wrap the function within an object
fun main() {
var foo = 3L
val local = object {
inline fun <reified T> f(): T {
return foo.bar<T>()
}
}
local.f<Int>()
}
f
is still local, in the sense that nothing outside of main
can access it directly.
If you really want to keep the f<Int>()
syntax, you can use the invoke
convention like this:
val f = object {
inline operator fun <reified T> invoke(): T {
return foo.bar<T>()
}
}
f<Int>() // this now works
But you will need one object for each local function you want to declare this way.