Kotlin's logical 'and' doesn't short-circuit? - kotlin

I was following along Kotlin's documentation at http://kotlinlang.org/docs/reference/null-safety.html#checking-for-null-in-conditions and tried adapting this example,
val b = "Kotlin"
if (b != null && b.length > 0) {
print("String of length ${b.length}")
} else {
print("Empty string")
}
to the case where b = null. In an IntelliJ Idea Kotlin project I have an app.kt with a main() function defined as:
fun main() {
val b = null
if (b != null && b.length > 0) {
print("String of length ${b.length}")
} else {
print("Empty string")
}
}
However, when I run this, I get two compilation errors:
Information:Kotlin: kotlinc-jvm 1.3.20 (JRE 11+28)
Information:2019-02-02 15:07 - Compilation completed with 2 errors and 0 warnings in 1 s 921 ms
/Users/kurtpeek/IdeaProjects/HelloWorld/src/app.kt
Error:(3, 24) Kotlin: Unresolved reference: length
Error:(4, 37) Kotlin: Unresolved reference: length
I understand that the compiler is evaluating b.length even though the first condition, b != null, is false. This surprises me because I thought that the first check was to 'short-circuit' the Boolean expression if needed and make the call to b.length 'safe'.
For example, in Python, you can do this:
In [1]: "foo" == "bar" and what.the.heck
Out[1]: False
which works even though what is not defined, because the and 'stops' since "foo" is not equal to "bar".
Is this indeed how Kotlin works? It seems like missing Python's 'short-circuiting' feature would be a limitation.

Kotlin's && operator will short circuit (just like Java's) but only at runtime. What you are experiencing is a compile time error. The big difference to remember especially when comparing Kotlin (or Java) to Python is that Kotlin and Java are statically typed and have a compilation phase. So you'll get a compilation error if the types don't match up.
Let's go through these one at a time...
val b = "Kotlin"
if (b != null && b.length > 0) {
...
}
In this case, Kotlin will correctly infer that b is the type String, because you clearly set it to a String ("Kotlin"). We should note here that the String type cannot ever contain null. Knowing that, the b != null part of your if statement is unnecessary. However, after evaluating that (to true, always) it will evaluate b.length because b is a String and therefore has a length property. This example should compile fine (I didn't test it).
And next...
val b = null
if (b != null && b.length > 0) {
...
}
This code will not compile, let's go over why...
This code looks really similar but has one huge difference. In this case because you just set b to null, Kotlin is going to infer that b is an Nothing?. It has no information as to what type you want b to be, and you've set it to null (and because it's a val, it will always be null). Because b is null, it makes b nullable.
So, given that, when we compile b != null, that will always fail, because b can't ever be something that isn't null. But wait! We're compiling now... and when we run into b.length Kotlin will throw a compilation error because Nothing? does not have a length property!
Essentially, by setting b to null and not providing a type hint, Kotlin takes the only path it can to infer the type - Nothing?.

From your linked text: "Note that this only works where b is immutable (i.e. a local variable which is not modified between the check and the usage or a member val which has a backing field and is not overridable)".
val b=null is immutable, but since the type of null cannot be inferred nor stored, it cannot be used as the source in a valid shortcut.
If you changed to code to give it a nullable type, and set that null, this would work.

Related

Why in kotlin "something != null || return" does not perform smartcast, but "if (something == null) return" yes

Given a function. for example:
suspend fun getUser(userId: Int): User? {
val result: UserApiResult? = fetchTheApi(userId)
//result != null || return null // Not smartcast
if (result == null) return null // Will make an smartcast of result from UserApiResult? to UserApiResult
return User(result.email, result.name)
}
Inside my IDE, specifically Android Studio. The first condition won't perform a smartcast even though it visibly does the same thing as the second condition (unless it's doing some dark things under the hood).
There is no good technical reason for smart casting to not take effect.
But it is jankier than you are giving it credit for. The only reason result != null || return null compiles is because return null has type Nothing and you can coerce Nothing to anything (in this case: Boolean).
The compiler should be able to reason that result != null as otherwise we would have obtained an instance of Nothing (which is impossible). But I'm personally glad I'll never have to see || return null in code review and I imagine the reasons for this not working are not a mistake by the Koltin devs.
Speculation on my part is that the compiler coerces the Nothing from return null to Boolean and loses the semantics of that branch being impossible to return from.
I think it's just a limitation of the current compiler. Building that code fails with the current compiler, but if you switch to the new K2 compiler (still in Alpha at the moment) compilation succeeds.
Example:
fun returnSomething(): String? = null
fun doSomething(): String? {
val result: String? = returnSomething()
result != null || return null
return result.length.toString()
}
fun main() {
println(doSomething())
}
Build output:
Kotlin: kotlinc-jvm 1.7.10 (JRE 1.8.0_212-b10)
Kotlin: ATTENTION!
This build uses experimental K2 compiler:
-Xuse-k2
Kotlin: performing incremental compilation analysis
Updating dependency information… [coroutines-test]
Running 'after' tasks
Finished, saving caches…
Executing post-compile tasks...
Synchronizing output directories...
01/11/2022, 18:01 - Build completed successfully with 4 warnings in 9 sec, 296 ms

What does Kotlin ?: return expression means [duplicate]

I can't figure out what ?: does in for example this case
val list = mutableList ?: mutableListOf()
and why can it be modified to this
val list = if (mutableList != null) mutableList else mutableListOf()
TL;DR: If the resulting object reference [first operand] is not null, it is returned. Otherwise the value of the second operand (which may be null) is returned. Additionally, the operator can throw an exception if null is returned.
The Elvis operator is part of many programming languages, e.g. Kotlin but also Groovy or C#.
I find the Wikipedia definition pretty accurate:
In certain computer programming languages, the Elvis operator ?: is a binary operator that returns its first operand if that operand is true, and otherwise evaluates and returns its second operand. It is a variant of the ternary conditional operator, ? :, found in those languages (and many others): the Elvis operator is the ternary operator with its second operand omitted.
The following is especially true for Kotlin:
Some computer programming languages have different semantics for this operator. Instead of the first operand having to result in a boolean, it must result in an object reference. If the resulting object reference is not null, it is returned. Otherwise the value of the second operand (which may be null) is returned. If the second operand is null, the operator is also able to throw an exception.
An example:
x ?: y // yields `x` if `x` is not null, `y` otherwise.
x ?: throw SomeException() // yields `x` if `x` is not null, throws SomeException otherwise
The Elvis Operator is represented by a question mark followed by a colon: ?: and it can be used with this syntax:
first operand ?: second operand
It enables you to write a consise code, and works as such:
If first operand isn't null, then it will be returned. If it is null, then the second operand will be returned. This can be used to guarantee that an expression won't return a null value, as you'll provide a non-nullable value if the provided value is null.
For example(in Kotlin):
fun retrieveString(): String { //Notice that this type isn't nullable
val nullableVariable: String? = getPotentialNull() //This variable may be null
return nullableVariable ?: "Secondary Not-Null String"
}
In this case, if the computed value of getPotentialNull is not null, it will be returned by retrieveString; If it is null, the second expression "Secondary Not-Null String" will be returned instead.
Also note that the right-hand side expression is evaluated only if the left-hand side is null.
In Kotlin, you could use any expression as second operand, such as a throw Exception expression
return nullVariable ?: throw IllegalResponseException("My inner function returned null! Oh no!")
The name Elvis Operator comes from the famous American singer Elvis Presley. His hairstyle resembles a Question Mark
Source: Wojda, I. Moskala, M. Android Development with Kotlin. 2017. Packt Publishing
This is called the Elvis operator and it does... Exactly what you've described in your question. If its left hand side is a null value, it returns the right side instead, sort of as a fallback. Otherwise it just returns the value on the left hand side.
a ?: b is just shorthand for if (a != null) a else b.
Some more examples with types:
val x: String? = "foo"
val y: String = x ?: "bar" // "foo", because x was non-null
val a: String? = null
val b: String = a ?: "bar" // "bar", because a was null
Let's take a look at the defintion:
When we have a nullable reference r, we can say "if r is not null, use
it, otherwise use some non-null value x":
The ?: (Elvis) operator avoids verbosity and makes your code really concise.
For example, a lot of collection extension functions return null as fallback.
listOf(1, 2, 3).firstOrNull { it == 4 } ?: throw IllegalStateException("Ups")
?: gives you a way to handle the fallback case elgantely even if you have multiple layers of fallback. If so, you can simply chain multiply Elvis operators, like here:
val l = listOf(1, 2, 3)
val x = l.firstOrNull { it == 4 } ?: l.firstOrNull { it == 5 } ?: throw IllegalStateException("Ups")
If you would express the same with if else it would be a lot more code which is harder to read.
The elvis operator in Kotlin is used for null safety.
x = a ?: b
In the above code, x will be assigned the value of a if a is not null and b if a is null.
The equivalent kotlin code without using the elvis operator is below:
x = if(a == null) b else a
Simply we can say that, you have two hands. You want to know, is your left hand working right now?. If left hand not working, return empty else busy
Example for Java:
private int a;
if(a != null){
println("a is not null, Value is: "+a)
}
else{
println("a is null")
}
Example for Kotlin:
val a : Int = 5
val l : Int = if (a != null) a.length else "a is null"
Consider below example,
var myStr:String? = null
//trying to find out length of myStr, but it could be null, so a null check can be put as,
val len = if (myStr != null){
myStr.length
}
else{
-1
}
Using the elvis operator, the above code can be written in a single line
val len = myStr?.length ?: -1 // will return -1 if myStr is null else will return length
In addition to what has been already stated there is one good pattern that was not obvious for me, but which is common, e.g. you're writing a long function, but if something is null there is no sense to continue and the only thing you can do is to return from the function. Normally you'd write
something = expression
if (something == null) {
return
}
With elvis it becomes shorter and more elegant:
something = expression ?: return
Basically, if the left side of Elvis returns null for some reason, returns the right side instead.
i.e.
val number: Int? = null
println(number ?: "Number is null")
So, if number is NOT null, it will print number, otherwise will print "Number is null".
A little addition though is this
X = A ?: B
X will still be null if both A and B evaluate to null
Therefore, if you want X to always be non-null, make sure B is always a non-null or that B always evaluates to non-null if it's a function or expression.

Why is my Kotlin comparable not makign correct equality comparisons?

I am currently trying to make a comparable object and working on the compareTo() function, for which I wrote the following code
class InfoAcad(e: String, m: String, c: Int): Comparable<InfoAcad> {
override operator fun compareTo(other: InfoAcad): Int {
if (this.e < other.e) return -1
if (this.e > other.e) return 1
if (this.e == other.e && this.m < other.m) return -1
if (this.e == other.e && this.m > other.m) return 1
return 0
}
}
The idea is that e is an ID number inputted as a string, which always follows the format XX-XXX where every X character is an integer between 0 and 9, and m is a course code following the format LL-XXX where each L character is a capital letter between A and Z and the X characters are integers between 0 and 9 like in the ID numbers. The objects are first compared by their ID number, and if the ID numbers are equal they are then compared by the course code, if both values are the same then the objects are equal, the c parameter is not taken into account in the comparison. I found out yesterday that I could compare strings directly in Kotlin in < and > relations, so I decided to try using that to make the task of comparing the InfoAcad objects a bit easier on myself, however when I make a main function to test the comparisons, the equality always returns a false value independently of what is in the string values of the InfoAcad objects. Here's said main function:
fun main() {
var A = InfoAcad("18-10125", "CI-2526", 3)
var B = InfoAcad("18-10125", "CI-2526", 5)
println("A = B: " + (A == B).toString()) //true
println("A < B: " + (A < B).toString()) //false
ptintln("A > B: " + (A > B).toString()) //false
}
When I change characters in the ID and course code values the inequality relations work just as intended, so what could be causing the equality relation to always return false? I appreciate and thank any responses in advance.
Note: I have also tried giving A and B the same c value, the equality part still returned false.
Override the equals function as well, or use a data class.
compareTo is only used for the < and > operators. The == operator is implemented by the separate equals function.
You can find the available operators, and the functions you need to override for each, in the Operator overloading section of the Kotlin docs.
If you don't override the equals function, the default behaviour is for it to use object identity. That means that two different objects, even if they contain the same fields, will never be considered equal.
There is however a nice shortcut for what you want to do! Kotlin will automatically generate an equals function for you if you make your class a data class. It's a good fit for classes like yours, whose main purpose is to hold data.
Because == and != translates to a call to equals(other: Any?): Boolean method, from kotlinlang
Expression Translated to
a == b a?.equals(b) ?: (b === null)
a != b !(a?.equals(b) ?: (b === null))
These operators only work with the function equals(other: Any?): Boolean, which can be overridden to provide custom equality check
implementation. Any other function with the same name (like
equals(other: Foo)) will not be called.

Not nullable value required to call 'component1()' function of destructuring declaration initializer

Is it possible to make the following code to compile in Kotlin?
val variable: String? = "string"
val (a, b) = variable?.run {
1 to 2
}
The compiler does not allow destructuring because the expression on the right-hand side is typed as a nullable Pair<Int, Int>?, and it's unclear what values a and b should get in case variable is null.
To solve this, you need to get a not-null expression after =.
There's a lot of different ways to deal with nullable values and produce a not-null value from a nullable one, see: In Kotlin, what is the idiomatic way to deal with nullable values, referencing or converting them
For example, if you want to provide fallback values for a and b, then use the ?: operator as follows:
val (a, b) = variable?.run {
1 to 2
} ?: (0 to 0)
An alternative, for example, would be to check variable for null first:
val (a, b) = checkNotNull(variable) { "variable should never be null" }.run {
1 to 2
}
Null doesn't have any destructuring declarations. If you want a value of null to destructure like it's a pair of nulls, you could add these extensions:
operator fun <T> Pair<T, *>?.component1() = this?.component1()
operator fun <T> Pair<*, T>?.component2() = this?.component2()
Otherwise, as the other answer shows, you need to provide a default using the Elvis operator.
It's not automatic because it doesn't know what you want. Depending on what you're doing with it, 0 to 0 may be most appropriate, or maybe -1 to -1 or 0 to null or null to null.
The question is, what do you want to do if your variable is null? If you want to throw an exception, go with require or check as #hotkey suggested.
However I have the case where I just want to return if the value is null. So I wrote myself a little helper function that allows for this:
private inline fun <T> T?.exitIfNull(exitBlock: () -> Nothing): T {
if (this == null)
exitBlock()
else
return this
}
You can call this function as follows:
val (a, b) = variable?.run {
1 to 2
}.exitIfNull {
return
}
A nice little use of the Nothing keyword in Kotlin that I personally find quite fascinating

What does ?: do in Kotlin? (Elvis Operator)

I can't figure out what ?: does in for example this case
val list = mutableList ?: mutableListOf()
and why can it be modified to this
val list = if (mutableList != null) mutableList else mutableListOf()
TL;DR: If the resulting object reference [first operand] is not null, it is returned. Otherwise the value of the second operand (which may be null) is returned. Additionally, the operator can throw an exception if null is returned.
The Elvis operator is part of many programming languages, e.g. Kotlin but also Groovy or C#.
I find the Wikipedia definition pretty accurate:
In certain computer programming languages, the Elvis operator ?: is a binary operator that returns its first operand if that operand is true, and otherwise evaluates and returns its second operand. It is a variant of the ternary conditional operator, ? :, found in those languages (and many others): the Elvis operator is the ternary operator with its second operand omitted.
The following is especially true for Kotlin:
Some computer programming languages have different semantics for this operator. Instead of the first operand having to result in a boolean, it must result in an object reference. If the resulting object reference is not null, it is returned. Otherwise the value of the second operand (which may be null) is returned. If the second operand is null, the operator is also able to throw an exception.
An example:
x ?: y // yields `x` if `x` is not null, `y` otherwise.
x ?: throw SomeException() // yields `x` if `x` is not null, throws SomeException otherwise
The Elvis Operator is represented by a question mark followed by a colon: ?: and it can be used with this syntax:
first operand ?: second operand
It enables you to write a consise code, and works as such:
If first operand isn't null, then it will be returned. If it is null, then the second operand will be returned. This can be used to guarantee that an expression won't return a null value, as you'll provide a non-nullable value if the provided value is null.
For example(in Kotlin):
fun retrieveString(): String { //Notice that this type isn't nullable
val nullableVariable: String? = getPotentialNull() //This variable may be null
return nullableVariable ?: "Secondary Not-Null String"
}
In this case, if the computed value of getPotentialNull is not null, it will be returned by retrieveString; If it is null, the second expression "Secondary Not-Null String" will be returned instead.
Also note that the right-hand side expression is evaluated only if the left-hand side is null.
In Kotlin, you could use any expression as second operand, such as a throw Exception expression
return nullVariable ?: throw IllegalResponseException("My inner function returned null! Oh no!")
The name Elvis Operator comes from the famous American singer Elvis Presley. His hairstyle resembles a Question Mark
Source: Wojda, I. Moskala, M. Android Development with Kotlin. 2017. Packt Publishing
This is called the Elvis operator and it does... Exactly what you've described in your question. If its left hand side is a null value, it returns the right side instead, sort of as a fallback. Otherwise it just returns the value on the left hand side.
a ?: b is just shorthand for if (a != null) a else b.
Some more examples with types:
val x: String? = "foo"
val y: String = x ?: "bar" // "foo", because x was non-null
val a: String? = null
val b: String = a ?: "bar" // "bar", because a was null
Let's take a look at the defintion:
When we have a nullable reference r, we can say "if r is not null, use
it, otherwise use some non-null value x":
The ?: (Elvis) operator avoids verbosity and makes your code really concise.
For example, a lot of collection extension functions return null as fallback.
listOf(1, 2, 3).firstOrNull { it == 4 } ?: throw IllegalStateException("Ups")
?: gives you a way to handle the fallback case elgantely even if you have multiple layers of fallback. If so, you can simply chain multiply Elvis operators, like here:
val l = listOf(1, 2, 3)
val x = l.firstOrNull { it == 4 } ?: l.firstOrNull { it == 5 } ?: throw IllegalStateException("Ups")
If you would express the same with if else it would be a lot more code which is harder to read.
The elvis operator in Kotlin is used for null safety.
x = a ?: b
In the above code, x will be assigned the value of a if a is not null and b if a is null.
The equivalent kotlin code without using the elvis operator is below:
x = if(a == null) b else a
Simply we can say that, you have two hands. You want to know, is your left hand working right now?. If left hand not working, return empty else busy
Example for Java:
private int a;
if(a != null){
println("a is not null, Value is: "+a)
}
else{
println("a is null")
}
Example for Kotlin:
val a : Int = 5
val l : Int = if (a != null) a.length else "a is null"
Consider below example,
var myStr:String? = null
//trying to find out length of myStr, but it could be null, so a null check can be put as,
val len = if (myStr != null){
myStr.length
}
else{
-1
}
Using the elvis operator, the above code can be written in a single line
val len = myStr?.length ?: -1 // will return -1 if myStr is null else will return length
In addition to what has been already stated there is one good pattern that was not obvious for me, but which is common, e.g. you're writing a long function, but if something is null there is no sense to continue and the only thing you can do is to return from the function. Normally you'd write
something = expression
if (something == null) {
return
}
With elvis it becomes shorter and more elegant:
something = expression ?: return
Basically, if the left side of Elvis returns null for some reason, returns the right side instead.
i.e.
val number: Int? = null
println(number ?: "Number is null")
So, if number is NOT null, it will print number, otherwise will print "Number is null".
A little addition though is this
X = A ?: B
X will still be null if both A and B evaluate to null
Therefore, if you want X to always be non-null, make sure B is always a non-null or that B always evaluates to non-null if it's a function or expression.