Kotlin function with unspecified return type - kotlin

In Kotlin how do you declare a function with an unspecified return type? For example, if I have a function that is to return a list of integers, but in the case of null input it should return just null, instead of a List.
How do I declare a function that could either return a MutableList or a null?

You just have to declare your type as nullable by using the ? at the end of the type declaration.
For example, this function takes a non-null Boolean and returns either a MutableList of Int or a null:
fun maybeGetList(input: Boolean): MutableList<Int>? =
if (input) mutableListOf(1) else null
Kotlin has quite extensive documentation on the subject.

Todd gave an good answer based on what you asked for, but if you are using Kotlin then it might be better to learn to use it properly.
Using null should be avoided as much as possible, that is why Kotlin even has null-safe types so it forces you to rethink your code and try to write it without nasty ?, just look at that sign, it is like it asks you do you really want to do this.
Now in your case you even have 2 great options for avoiding null and writing more idiomatic Kotlin:
Return empty list:
fun getList(condition: Boolean): List<Int>
= if(condition) listOf(1,2,3) else emptyList()
fun getMutableList(condition: Boolean): MutableList<Int>
= if(condition) mutableListOf(1,2,3) else mutableListOf()
Use Optional from Java:
fun getOptionalList(condition: Boolean): Optional<List<Int>>
= if (condition) Optional.of(listOf(1, 2, 3)) else Optional.empty()
You might think that doing this adds complexity but its quite the opposite, using null adds much more complexity because when you return it you must handle that null on every place you call this method, this way you encapsulate dangerous state instead of spreading it.

Related

Same type for receiver and argument in Kotlin function

Is there any difference between these two Kotlin extension functions?
fun Any?.f(o: Any?) = 100
fun <T> T.g(o: T) = 100
Is it possible to rewrite g in such a way that the type of its argument and receiver are forced to be the same?
That is, 10.g(5) and "x".g("y") are OK, but 10.g("y") does not compile.
Edit:
Given this, I guess the answer to my second question is no, uless one adds additional arguments.
I believe this is not possible officially at the time of writing this answer (Kotlin 1.7.20).
However, internally Kotlin compiler supports such case, it allows to change the default behavior and use exact type parameters. This is controlled by the internal #Exact annotation and it is used in many places across the Kotlin stdlib.
With some hacking we can enable this behavior in our own code:
#Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun <T> #kotlin.internal.Exact T.g(o: #kotlin.internal.Exact T) = 100
Of course, this is purely a hack and it may stop working in future versions of Kotlin.
Update
Answering your first question on whether there is a difference between using Any and T. Generic functions make the most sense if the type parameter is not only consumed, but also passed somewhere further. For example, if the function returns T or it receives an object that consumes T:
fun main() {
var result = 5.g(7)
}
fun <T> T.g(o: T): T = if (...) this else o
In this case result is of type Int. If we use Any instead of T, result would have to be Any as well.

How to safe-cast a null into a generic type <T>?

I want to know if there's a way to make a safe cast from null, the next example throws an UNCHECKED CAST warning:
fun <T> notInitialized(): T = null as T
So, If anyone has an idea of how to make a safe cast from this function please let me know!
You can do fun <T> notInitialized(): T? = null - you need to return a nullable type (otherwise your cast is explicitly unsafe), and since you're already specifying the return type you don't need to cast null as T?. Or you could do that and skip the return type, fun <T> notInitialized() = null as T?
Either way you're just returning null, which isn't any specific type - you're just telling the caller to treat it as one. And that type needs to be nullable
As an alternative to the generic answer (which is the usual way to approach these things), you could do this:
fun notInitialised(): Nothing? = null
Nothing is the ‘bottom’ type, which has no values and is the subset of all other types. So Nothing? is a type with just one value (null), and is a subtype of all nullable types. This means you can assign it to any nullable type without needing any type inference, e.g.:
val a: Int? = notInitialised()
But I still don't understand the purpose of this — it doesn't seem to have any benefit over just using null directly. If you're using null to represent an uninitialised value (as opposed to an unknown value, a missing value, an inapplicable value, an unavailable value, an undefined value, an unchanged value, a secret value, or any of the other subtly-different things that people use null to mean), then that should be spelled out in the property/method/variable's doc comment — in which case there's no point spelling it out again in the code.

Kotlin expression fun vs normal fun - differences

Let's assume that I have two functions which do the same stuff.
First one:
fun doSomething() = someObject.getSomeData()
Second one:
fun doSomething(): SomeData {
return someObject.getSomeData()
}
Are there any technical differences between expression functions and standard function in Kotlin excluding the way how they look?
Is compiled output the same?
Are there any advantages using one instead another?
As #Sơn Phan says, they both compile to exactly the same bytecode.
So the differences are simply about conciseness.  The expression form omits the braces and return; it also lets you omit the return type (using type inference as needed).  As the question illustrates, the expression form can be shorter — and when all else is equal, shorter tends to be easier to read and understand.
So whether the expression form is appropriate is usually a matter of style rather than correctness.  For example, this function could be on one line:
fun String.toPositiveIntegers() = split(",").mapNotNull{ it.toIntOrNull() }.filter{ it >= 0 }
But it's a bit long, and probably better to split it.  You could keep the expression form:
fun String.toPositiveIntegers()
= split(",")
.mapNotNull{ it.toIntOrNull() }
.filter{ it >= 0 }
Or use a traditional function form:
fun String.toPositiveIntegers(): List<Int> {
return split(",")
.mapNotNull{ it.toIntOrNull() }
.filter{ it >= 0 }
}
(I tend to prefer the former, but there are arguments both ways.)
Similarly, I rather like using it when the body is a simple lambda, e.g.:
fun createMyObject() = MyObject.apply {
someConfig(someField)
someOtherConfig()
}
…but I expect some folk wouldn't.
One gotcha when using the expression form is the type inference.  Generally speaking, in Kotlin it's good to let the compiler figure out the type when it can; but for function return values, that's not always such a good idea.  For example:
fun myFun(): String = someProperty.someFunction()
will give a compilation error if the someFunction() is ever changed to return something other than a String — even a nullable String?.  However:
fun myFun() = someProperty.someFunction()
…would NOT give a compilation error; it would silently change the function's return type.  That can mask bugs, or make them harder to find.  (It's not a very common problem, but I've hit it myself.)  So you might consider specifying the return type, even though you don't need to, whenever there's a risk of it changing.
One particular case of this is when calling a Java function which doesn't have an annotation specifying its nullability.  Kotlin will treat the result as a ‘platform type’ (which means it can't tell whether it's nullable); returning such a platform type is rarely a good idea, and IntelliJ has a warning suggesting that you specify the return type explicitly.
1. Compiled output
Yes the compiled output will be completely the same
2. Advantage
You usually use expression function when the body of a function is only one line of expression to make it a oneliner function. Its advantage mainly about making the code more concise. Imagine instead of all the brackets and return, you only need a = to make things done.

Is `a?.let{} ?: run{}` idiomatic in Kotlin?

I saw the following comment in a S.O. post, and I'm intrigued:
why don't you use if for null checks? a?.let{} ?: run{} is only appropriate in rare cases, otherwise it is not idiomatic – voddan May 15 '16 at 7:29 best way to null check in kotlin?
Why is that construct "only appropriate in rare cases"?
The lead engineer for Kotlin says,
run allows you to use multiple statements on the right side of an elvis operator https://stackoverflow.com/a/51241983/6656019
although I admit that's not actually endorsing it as idiomatic. Both of these posts seem to be from very well respected S.O. Kotlin contributors.
The post that inspired the original comment mentions that the let part of the expression is important if a is mutable. In that case, you'll need a?.let{} ?: run{} instead of if{} else {}.
I find I like the "let Elvis run" construct. Should I avoid it in most cases?
Thanks for any insight.
It's dangerous to conflate foo?.let { bar(it) } ?: baz() with if (foo != null) bar(foo) else baz().
Say you have a function: fun computeElements(): List<Int>? = emptyList()
Consider this code:
val maxElement = computeElements()?.let { it.max() } ?: return
println("Max element was $maxElement")
Compared to:
val list: List<Int>? = computeElements()
val maxElement = if (list != null) list.max() else return
println("Max element was $maxElement")
You may think these are two equivalent forms. However, if you run both, you'll see that the former does not print anything to stdout!
This is because it.max() returns null for an empty list (because there is no max element), which causes the right-hand side of the Elvis expression to be evaluated, and so the function returns early.
In short, ?.let { ... } ?: ... allows both branches of the "if-else" to be evaluated, which is dangerous. Aside from this form not being readable (if-else is universally understood, while let-run is not), subtle bugs can occur.
In that case, you'll need a?.let{} ?: run{} instead of if{} else {}
No, you can omit the run part of run { statement } and use a?.let{} ?: statement.
Should I avoid it in most cases?
You should use it when you need it. E.g. when you want to run multiple statements in that scenario. It is pointed out that that is a rare scenario. Often you will see just a single statement on the right hand side of an elvis operator.
And of course don't use it when you don't need it. Keep the code simple.

Kotlin: null and "Overload resolution ambiguity"

I want to call a overloaded java-function from Kotlin. I want to use a null for parameter that significant to a overload resolution.
How to specify IntArray type for null value?
I don't like a solution with additional varibale of common type.
Instead of a variable just cast it, i.e. null as IntArray?, e.g.:
origImg.data.getSamples(0, 0, origImg.width, origImg.height, 0, null as IntArray?)
Note that this is the same behaviour as in Java, where you also needed to cast null, e.g. (int[]) null, to call the appropriate overloaded method.
You could build a function that gives you a ~typed null (if it doesn't exist yet) with a reified type:
inline fun <reified T>typedNull(): T? = null
and calling it with:
typedNull<IntArray>()
But then again, null as IntArray? is clear enough I think and people know it already.