We know that kotlin allows us to use default parameters, but how does it determine which func to invoke when overload happens? like this below, the result is that the first test is invoked rather than the second, but why?
fun test() {
}
fun test(a: Int = 1) {
}
fun main() {
test()
}
The Kotlin language specification sets out rules for overload resolution.
First it states the general rule:
The compiler should first pick a number of overload candidates, which
form a set of possibly intended callables (overload candidate set,
OCS), and then choose the most specific function to call based on the
types of the function and the call arguments.
Then, later, in explaining how the most specific function is determined, it states:
For each candidate we count the number of default parameters not
specified in the call (i.e., the number of parameters for which we use
the default value). The candidate with the least number of
non-specified default parameters is a more specific candidate
So there you go. In your example the test() function without the default parameter will be chosen as it has a lesser number of non-specified default parameters, and is thus more specific.
Related
So I have 2 overloaded score functions, one of which takes a performance param of type Performance, and the other which takes a performances param, which is a List<Performance>. The former returns a double, while the latter returns a double array. (Another team owns the Scorer class, so fixing it to not overload like this isn't really doable rn; breaking changes and all).
I want to test 2 branches, one with each implementation, how can I mock these using kotlin's mockk?
The former can be mockked using ofType(Performance::class),
scorer: Scorer = mockk()
every { scorer.score(????) } returns doubleArrayOf(0.9)
What goes there?
ofType(List<Performance>::class) doesn't work because apparently that can't be done with generics.
not(ofType(CandidateFeature::class)) results in a compile-time error Type mismatch: inferred type is DoubleArray but Double was expected
How do I explicitly choose which overriden signature I'm trying to call?
You can use withArg
every { scorer.score(withArg<Performance> {} ) returns mockData
every { scorer.score(withArg<List<Performance>> {} ) returns mockData
I know there was documented in main kotlin page, but there is no clear explanation about when to use it, why this function need a receiver as a function. What would be the correct way to create a correct definition of inline function.
This is inline function
inline fun String?.toDateString(rawDateFormat: String = MMMM_DD_YYYY, outputDate: String = MM_DD_YYYY, block: (date: String) -> String): String {
return try {
var sdf = SimpleDateFormat(rawDateFormat, Locale.US)
val date = sdf.parse(this.orEmpty())
sdf = SimpleDateFormat(outputDate, Locale.US)
block(sdf.format(date ?: Date()).orEmpty())
} catch (ex: Exception) {
block("")
}
}
The same way we also can do
inline fun String?.toDateString(rawDateFormat: String = MMMM_DD_YYYY, outputDate: String = MM_DD_YYYY): String {
return try {
var sdf = SimpleDateFormat(rawDateFormat, Locale.US)
val date = sdf.parse(this.orEmpty())
sdf = SimpleDateFormat(outputDate, Locale.US)
sdf.format(date ?: Date()).orEmpty()
} catch (ex: Exception) {
""
}
}
If anyone could have a detail explanation about this?
Edit:
I understand that the inline function will insert the code whenever it called by the compiler. But this come to my attention, when I want to use inline function without functional parameter receiver type the warning show as this in which should have a better explain. I also want to understand why this is such recommendation.
There are few things here.
First, you ask about using a function with a receiver. In both cases here, the receiver is the String? part of String?.toDateString(). It means that you can call the function as if it were a method of String, e.g. "2021-01-15 12:00:00".toDateString(…).
The original String? is accessible as this within the function; you can see it in the sdf.parse(this.orEmpty()) call. (It's not always as obvious as this; you could simply call sdf.parse(orEmpty()), where the this. is implied.)
Then you ask about inline functions. All you have to do is to mark the function as inline, and the compiler will automatically insert its code wherever it's called, instead of defining a function in the usual way. But you don't need to worry about how it's implemented; there are just a few visible effects in the code. In particular, if a function is inline and accepts a function parameter, then its lambda can do a few things (such as calling return) that it couldn't otherwise do.
Which leads us to what I think is your real question: about the block function parameter. Your first example has this parameter, with the type (date: String) -> String — i.e. a function taking a single String parameter and returning another String. (The technical term for this is that toDateString() is a higher-order function.)
The toDateString() function calls this block function before returning, applying it to the date string it has formatted before returning it to the caller.
As to why it does this, it's hard to tell. That's why we put documentation comments before functions: to explain anything that's not obvious from the code! Ideally, there would be a comment explaining why you're required to supply a block lamdba (or function reference), when it's not vital to what the function does.
There are times when blocks passed this way are very useful. For example, the joinToString() function accepts an optional transform parameter, which it applies to each item before joining it to the list. If it didn't, the effect would be a lot more awkward to obtain. (You'd probably have to apply a map() to the collection before calling joinToString(), which would be less efficient.)
But this isn't one of those times. As your second example shows, toDateString() would work perfectly well without the block parameter — and then if you needed to pass the result through another function, you could just call it on toDateString()'s result.
Perhaps if you included a link to the ‘main kotlin page’ where you saw this, it might give some more context?
The edited question also asks about the IDE warning. This is shown when it thinks inlining a function won't give a significant improvement.
When no lambdas are involved, the only potential benefit from inlining a function is performance, and that's a trade-off. It might avoid the overhead of a function call wherever it's called — but the Java runtime will often inline small functions anyway, all on its own. And having the compiler do the inlining comes at the cost of duplicating the function's code everywhere it's called; the increased code size is less likely to fit into memory caches, and less likely to be optimised by the Java runtime — so that can end up reducing the performance overall. Because this isn't always obvious, the IDE gives a warning.
It's different when lambdas are involved, though. In that case, inlining affects functionality: for example, it allows non-local returns and reified type parameters. So in that case there are good reasons for using inline regardless of any performance implications, and the IDE doesn't give the warning.
(In fact, if a function calls a lambda it's passed, inlining can have a more significant performance benefit: not only does the function itself get inlined, but the lambda itself usually does as well, removing two levels of function call — and the lambda is often called repeatedly, so there can be a real saving.)
I am a newbie in Kotlin, I just started to learn it,
I get the following code example about literal/high order function:
fun myHigherOrderFun(functionArg: (Int)->String) = functionArg(5)
println ( myHigherOrderFun { "The Number is $it" })
prints "The Number is 5"
Which I have difficulty to understand: the function myHigherOrderFun get a lambda function as parameter but i can't understand, where is the (Int) input parameter? I see is passed in functionArg(5)... but i can't realize how is possible that?
Thanks in advance.
To start from the beginning, in Kotlin functions are first-class types, just like numbers and Strings and stuff. So a function can take another function as a parameter, and/or return a function as its result. A function which does this is called a ‘higher-order function’.
And that's what you have in your example! The line:
fun myHigherOrderFun(functionArg: (Int)->String) = functionArg(5)
defines myHigherOrderFun() as a function which takes one parameter, which is itself a function taking a single Int parameter and returning a String. (myHigherOrderFun() doesn't specify an explicit return type, so it's inferred to be a String too.)
The next line is probably where things are less clear:
println(myHigherOrderFun{ "The Number is $it" })
The first non-obvious thing is that it's calling myHigherOrderFun() with a parameter. Because that parameter is a lambda, Kotlin lets you omit the usual (…), and use only the braces.
The other non-obvious thing is the lambda itself: { "The Number is $it" }. This is a literal function taking one parameter (of unspecified type).
Normally, you'd have to specify any parameters explicitly, e.g.: { a: Char, b: Int -> /* … */ }. But if there's exactly one parameter, and you aren't specifying its type, then you can skip that and just refer to the parameter as it. That's what's happening here.
(If the lambda didn't reference it, then it would be a function taking no parameters at all.)
And because the lambda is being passed to something expecting a function taking an Int parameter, Kotlin knows that it must be an Int, which is why we can get away without specifying that.
So, Kotlin passes that lambda to the myHigherOrderFun(), which executes the lambda, passing 5 as it. That interpolates it into a string, which it returns as the argument to println().
Many lambdas take a single parameter, so it gets used quite a lot in Kotlin; it's more concise (and usually more readable) than the alternative. See the docs for more info.
I know how to read/interpret Java code and I can write it. However being new to kotlin I find code like below hard to read. Perhaps I am missing key concepts in the language.
But, how would you go about interpreting this code? Where do you propose one to start reading it in order to understand this piece of code quickly and efficiently? Left to right? Right to left? Break down parameters first? Look at return values?
inline fun <T : Any, R> ifNotNull(input: T?, callback: (T) -> R): R? {
return input?.let(callback)
}
So, like Java this is a generic function. It has two type parameters T which is of type 'Any' ('Any' is like 'Object' in Java) and R. The input parameter is a nullable T, as denoted by the question mark. Nullable types mean that the value can be null. The other function parameter is a function that takes in a T (non nullable type) and returns R. The return type of the function is a nullable R. The body of the function says that if input is not null, call and pass that to the callback and return that value. If input is null, then null is what gets returned.
Let's dissect the function definition piece by piece:
inline: Indicates that the code of the function will be copied directly to the call site, rather than being called like a normal function.
fun: We're defining a function.
<T : Any, R>: The function takes two generic type parameters, T and R. The T type is restricted to the Any type (which is Kotlin's Object-type). That might seem redundant, but what it actually says is that T cannot be a nullable type (Any?).
ifNotNull: The name of the function.
input: T?: The first parameter of type T?. We can put the ? on the T type here because we restricted it to non-nullable types in the type declaration.
callback: (T) -> R: The second parameter is of type (T) -> R, which is a function type. It's the type of a function that takes a T as input and returns an R.
: R?: The function returns a value of type R or null.
return input?.let(callback): The function body. The let function takes a function parameter, calls it with its receiver (input), and then returns the result of the function. The ? after input says that let will be called only if input is not null. If input is null, then the expression will return null.
The function is equivalent to this Java method (except for the inlining and nullable types):
public <T, R> R ifNotNull(final T input, final Function<T, R> callback) {
if (input == null) {
return null;
}
return callback.apply(input);
}
Matt's answer explains everything well in one go; I'll try to look at how you might go about reading such code.
Skipping over the first word for now, the most important thing is the second word: fun. So the whole thing is defining a function. That tells you what to expect from the rest.
The braces tell you that it's a block function, not a one-liner, so the basic structure you're expecting is: fun name(params): returnType { code }. The rest is filling in the blanks! (This fits the general pattern of Kotlin declarations, where the type comes second, after a colon. The Java equivalent would of course be more like returnType name(params) { code }.)
As with Java, the stuff in angle brackets is giving generic parameters, so we can skip that for now and go straight to the next most important bit, which is the name of the function being defined: ifNotNull.
Armed with those, we can read the rest. inline is a simple modifier, telling you that the function will be inlined by the compiler. (That enables a few things and restricts a few others, but I wouldn't worry about that now.)
The <T : Any, R> gives the generic parameter types that the function uses. The first is T, which must be Any or a subtype; the second is R, which is unrestricted.
(Any is like Java's Object, but can't be null; the topmost type is the related Any?, which also allows null. So except for the nullability, that's equivalent to the Java <T extends Object, R>.)
Going on, we have the function parameters in parentheses. Again, there are two: the first is called input, and it's of type T?, which means it accepts any value of type T, and also accepts null. The second parameter is called callback, and has a more complicated type, (T) -> R: it's a function which takes a T as its parameter, and returns an R. (Java doesn't have function types as such, so that probably looks strangest. Java's nearest equivalent is Function<R, T>.)
After the parentheses comes the return type of this function itself, R?, which means it can return either an R or null.
Finally, in braces is the actual code of the function. That has one line, which returns the value of an expression. (Its effect is to check whether the value of input is null: if so, it returns the null directly. Otherwise, it calls the callback function given in the parameter, passing input as its parameter, and returns its result.)
Although that's a short declaration, it's quite abstract and packs a lot in, so it's no wonder you're finding it hard going! (The format is similar to a Java method declaration — but Kotlin's quite expressive, so equivalent code tends to be quite a bit shorter than Java. And the generics make it more complex.) If you're just starting to learn Kotlin, I'd suggest something a bit easier :-)
(The good news is that, as in Java, you don't often need to read the stdlib code. Although Kotlin's doc comments are rarely up to the exemplary level of Java's, they're still usually enough.)
How can i make an arraylist of functions, and call each function easily? I have already tried making an ArrayList<Function<Unit>>, but when i tried to do this:
functionList.forEach { it }
and this:
for(i in 0 until functionList.size) functionList[i]
When i tried doing this: it() and this: functionList[i](), but it wouldn't even compile in intellij. How can i do this in kotlin? Also, does the "Unit" in ArrayList<Function<Unit>> mean return value or parameters?
Just like this:
val funs:List<() -> Unit> = listOf({}, { println("fun")})
funs.forEach { it() }
The compiler can successfully infer the type of funs here which is List<() -> Unit>. Note that () -> Unit is a function type in Kotlin which represents a function that does not take any argument and returns Unit.
I think there are two problems with the use of the Function interface here.
The first problem is that it doesn't mean what you might think. As I understand it, it's a very general interface, implemented by all functions, however many parameters they take (or none). So it doesn't have any invoke() method. That's what the compiler is complaining about.
Function has several sub-interfaces, one for each 'arity' (i.e. one for each number of parameters): Function0 for functions that take no parameters, Function1 for functions taking one parameter, and so on. These have the appropriate invoke() methods. So you could probably fix this by replacing Function by Function0.
But that leads me on to the second problem, which is that the Function interfaces aren't supposed to be used this way. I think they're mainly for Java compatibility and/or for internal use by the compiler.
It's usually much better to use the Kotlin syntax for function types: (P1, P2...) -> R. This is much easier to read, and avoids these sorts of problems.
So the real answer is probably to replace Function<Unit> by () -> Unit.
Also, in case it's not clear, Kotlin doesn't have a void type. Instead, it has a type called Unit, which has exactly one value. This might seem strange, but makes better sense in the type system, as it lets the compiler distinguish functions that return without an explicit value, from those which don't return. (The latter might always throw an exception or exit the process. They can be defined to return Nothing -- a type with no values at all.)