One other helpful convention is that if a function literal has only one parameter, its declaration may be omitted (along with the ->), and its name will be it
So, a lambda without param declaration, is a lambda with or one or none parameters.
fun onChange(lambda: (newValue: String)->Unit) = lambda("first")
fun onChange(lambda: (oldValue: String, newValue: String)->Unit) = lambda("first", "second")
fun main(vararg args: String) {
onChange{ first, second->println("$first -> $second")}//prints 'first -> second'
onChange{ it->println(it) } //prints 'first'
onChange{ println(it) } //not working -> overload resolution ambiguity
}
The last onChange is not working, because the compiler sais it can be applied to both functions.
This is however not the truth, because it can’t be applied to the lambda with two parameters.
Is it possible for the compiler to infer this?
It is very unlikely that the compiler could. If you leave of the parameter type, the compiler only has the following to work with:
fun onChange(lambda) = lambda("first")
fun onChange(lambda) = lambda("first", "second")
Inferring the type of the parameters of the lambdas won’t be a problem: String
, but what is the return type of the lambdas? The only safe choice would be defaulting to Unit
, I guess.
But even if the compiler could do it, explicit parameter types are needed for acceptable compiler performance according to Why can not type of function parameters with default value be omited?.
Note: You don’t have to specify parameter names for function types. The following is equivalent to your code:
fun onChange(lambda: (String)->Unit) = ...
fun onChange(lambda: (String, String)->Unit) = ...
sorry, for the inconvenience, but it seems like it wasn’t clear what I meant.
Therefore, I updated the main post.
thanks for the hint about the parameternames, but when the params are named, it’s easier to call, due to the autocompletion of Intellij.
At this moment we haven’t decided yet what { println(it) }
should mean when there are several overloads accepting functional types with the different number of parameters (consider also onChange
overload taking a lambda with no parameters)
You can add your use case to the similar issue https://youtrack.jetbrains.com/issue/KT-18451
Posted.
Ps. I think a combination of a change with no parameters and with one parameters should be a ambiguous overload. This is also explainable with the sentence of the documentation.
In this context, I’m wondering what the meaning of a lambda in a multi-parameter parameter is (even if it doesn’t refer to any of those parameters) where there are no explicit lambda parameters. In addition, why is the parenthesised version different from the non-parenthesized version.