I have a function signature similar to this ```fun...
# getting-started
d
I have a function signature similar to this
Copy code
fun <T> test(param: T, func: () -> T) {}
Is there any way to enforce that param and lambda return types are the same? Current version allows calling the function like this
Copy code
test(1) { "1" }
The reason is that the inferred type is the closest common type. So explicitly specifying the generic type would help but I would like to avoid that if possible.
j
It seems that exposing the first parameter as an argument to the second will enforce it. Not sure if that's what you're looking for but I think for now it's the best you can do.
Copy code
fun <T> test(param: T, func: (T) -> T) {
    val funcResult = func(param)
}

val test = test(1) { "1" } // Error
d
@Joshua Hansen That's a nice and acceptable workaround. Thanks!
Sadly, the workaround isn't so nice once you have multiple type params because then this trick slightly leaks to the callers via the specified but ignored lambda arguments:
Copy code
fun <T, R> test(param1: T, param2: R, func: (T, R) -> Pair<T, R>) {
    val funcResult = func(param1, param2)
}

val test = test(1, 2) { _, _ -> "1" } // Error
Hmm, I suppose even this can be fixed. It looks more and more hacky, though 🙂
Copy code
fun <T, R> test(param1: T, param2: R, func: (Pair<T, R>) -> Pair<T, R>) {
    val funcResult = func(param1 to param2)
}
The workaround doesn't work with Unit for some reason, i.e. this compiles fine:
Copy code
fun <T> test(param: T, func: (T) -> T) {
    val funcResult = func(param)
}

val test = test(Unit) { "1" } // compiles ok
Why is that? I thought that
Unit
has no special place in the type hierarchy.
y
Lambdas that need to return
Unit
don't have to explicitly return it. Hence, the "1" expression is ignored, and Unit is returned. IntelliJ should probably report an error that "1" is unused
k
In that code,
{ "1" }
is treated as a function of type
() -> Unit
with an expression whose result is not used. Unused results are very common, for example
Set.add
returns a Boolean but we are allowed to ignore it, so in the same way "1" returns a String but we ignore it. IntelliJ reports a warning (it's not an error).
d
Makes sense. Unfortunately, Intellij doesn't report anything.
I mean it doesn't report anything in my particular case where of course I don't have a constant in the lambda but a function call (which can have side effects). I guess there's nothing I can do about it.