Reputation: 650
So I was solving Koans problem and through my overly complex solution bumped into a thing that bothers me. I was using Int.compareTo() function on nullable types. It is "easy" if the first one is nullable because I just write:
val a : Int? = 1
val b : Int = 1
a?.compareTo(b)
But if b is nullable, then I was not able to get it to work, maybe I missed something somewhere? So what to do when this is the case?
val a : Int? = 1
val b : Int? = 2
a?.compareTo(b)
I get a syntax error saying "None of the following functions can be called with the arguments supplied."
But, when I introduce this:
val a : Int? = 1
val b : Int? = 2
val x : Int = b ?: 0;
o1?.compareTo(x)
It works but it feels like it is not the right way to do this. Is there a better way?
Upvotes: 2
Views: 189
Reputation: 2668
You can do
val a: Int? = 1
val b: Int? = 2
b?.let {
a?.compareTo(b)
}
let
block will be executed only if b is not null.
Or just
if (a != null && b != null) {
a.compareTo(b)
}
I think second solution is very clear and easy to read.
Upvotes: 2
Reputation: 30686
the expression should be like this:
val result = b?.let { a?.compareTo(b) ?: -1 } ?: 1;
> a = 1 b = 2 ---> -1
> a = null b = 2 ---> -1
> a = null b = -1 ---> -1
> a = 1 b = null ---> 1
> a = -1 b = null ---> 1
> a = null b = null ---> 1 // the order is no matter
IF you want to let null
compare null
return 0
then the expression is a bit long:
val result = b?.let { a?.compareTo(b) ?: -1 } ?: a?.let { 1 } ?: 0;
Note: you don't care about the performance, since let
function is an inline function. which means it will generates the code like as below in java:
int result = b != null ? a != null ? a.compareTo(b) : -1 : a != null ? 1 : 0;
Upvotes: -1
Reputation: 9448
The only better way is to implement compareTo
yourself. The default compare does not know what result you want when you compare i.e. 12
to null
or null
to null
. It only knows how to compare actual numbers. I think your best way is to implement the behaviour you want for dealing with null
s.
Example implementation:
fun main(args: Array<String>) {
println(compareNullableInts(null, 2)) // -1
println(compareNullableInts(null, null)) // 0
println(compareNullableInts(2, null)) // 1
println(compareNullableInts(10, 5)) // 1
}
fun compareNullableInts(a: Int?, b: Int?): Int {
if (a == null && b == null) return 0
if (a == null) return -1
if (b == null) return 1
return a.compareTo(b)
}
Upvotes: 0
Reputation: 39843
You should try to implement your solution without nullability. But if you still need it and if it's safe to assume that null==0
you should not use the ?.
method call. It'll return you an Int?
as well. Just map both null
integers to 0.
(a?:0).compareTo(b?:0)
Upvotes: 0
Reputation: 9622
The Int.compareTo() method's signature is not defined for nullable arguments so it's not possible to do without ensuring null safety of the argument by e.g. using an elvis operator just as you have suggested.
Upvotes: 0