Kotlin Operators ?, ?., ?: open source implementation - kotlin

I am pretty new to Kotlin, I am looking at the null safety and Elvis operators and would like to know more on how these are implemented to work on top of JVM.
Operators I am interested to know the implementation of:
? ?. ?:
But I am unable to locate any source associated with these. Are the implementations hidden? From my IDE also I cannot locate any source related to these, magic?
From the Kotlinlang.org: It specifies that Kotlin is an open source language: Kotlin is an open-source statically typed programming language that targets the JVM, Android, JavaScript and Native
Note: I know I don't need to specify null on the right hand side of the Elvis, this is just to send my point across in the screen grab.

Disclaimer: I'm no expert on the Kotlin compiler. I just looked at the source code.
The tokens are defined here:
KtSingleValueToken SAFE_ACCESS = new KtSingleValueToken("SAFE_ACCESS", "?.");
KtSingleValueToken ELVIS = new KtSingleValueToken("ELVIS", "?:");
KtSingleValueToken QUEST = new KtSingleValueToken("QUEST", "?");
These tokens are parsed by the Kotlin compiler itself, they are not defined in Java. This is why you cannot jump to a definition - they are re-written by the compiler.
I don't know how they are implemented, but checking out the Kotlin source and using the above tokens as a starting point might be useful.

Those features are "embedded" into the language. So you can't really dig into the code at compile time. An equivalent example to this would be trying to get the implementation of a while loop or a when statement. Those are language features that just generate compiled code
One thing that you could do if you're curious would be to decompile a simple program using them and check the result. However, as the generated bytecode may include some optimizations, the result might differ between different use cases.
The most important thing you need to know is what they do and how to use them. You can find an example of equivalent behaviour between null safe operators and java code in the Kotlin Koans, in which this Java code
public void sendMessageToClient(
#Nullable Client client,
#Nullable String message,
#NotNull Mailer mailer
) {
if (client == null || message == null) return;
PersonalInfo personalInfo = client.getPersonalInfo();
if (personalInfo == null) return;
String email = personalInfo.getEmail();
if (email == null) return;
mailer.sendMessage(email, message);
}
can be rewritten in Kotlin as
val email = client?.personalInfo?.email
if (email != null && message != null) {
mailer.sendMessage(email, message)
}

You don't have to set null on the right side of the elvis operator, the elvis operator is for handling non nullable case.
val info:EuiccInfo? = msg?.euiccInfo
val info - defined as nullable so it can be set null as well, if msg is null (msg? means msg can be null too, and if msg is null it will not access to .euiccInfo) info will be null.
lets assume info defined as non nullable val
val info:EuiccInfo = msg?.euiccInfo
compiler will not allow you to set info null value because msg is nullable,
so you have to handle non null case.
val info: EuiccInfo = msg?.euiccInfo ?: someDefaultNonNullValue (EuiccInfo())
it's unnecessary (and nonsense) to handle null case with Elvis operator because it will be set null if msg is null or msg?.euiccInfo is null.

Related

Interoperability java-kotlin Nullable string crashing at runtime but why?

I have an alternative to my problem, but I still have 2 questions:
Why it's crashing
Why Intellij/compiler is not complaining
I provided a small example of my issue. Here is an overview (you can find the code just after)
Car.java is the java class with a simple getter annoted as nulllable
MyView.kt is the crashing at runtime example with no warning in Intellij or in gradle. (Crashing when the value is null)
MyView2.kt is not crashing at runtime (even if mType is null)
Library.kt (kotlin stdlib) is simply the expected call for the example (even if it's weird to see string.toString())
Car.java
#Nullable
private String mType;
#Nullable
public String getCarType() {
return mType;
}
MyView.kt (crashing)
val test: String = myCar.carType.toString()
MyView2.kt (not crashing)
val carType: String? = myCar.carType
val test2: String = carType.toString()
Library.kt (kotlin stdlib)
/**
* Returns a string representation of the object. Can be called with a null receiver, in which case
* it returns the string "null".
*/
public fun Any?.toString(): String
Thanks! I guess this is a corner case of the interop between kotlin and java? Or... someone is aware of a better explanation?
The clue to this difference is the optional marker ? in this line in MyView2.kt
val carType: String? = myCar.carType
- here you are declaring to the Kotlin compiler that you know that carType is nullable. (In turn the behaviour of .toString() will work even though it is called on a null object, as you showed from the docs.)
However things are different in MyView.kt because the code doesn't get as far as the .toString() call. Here you are directly using a platform type (i.e. Java) where null-safety rules cannot be deduced.
This documentation about Calling Java code from Kotlin explains:
Types of Java declarations are treated in Kotlin in a specific manner and called platform types. Null-checks are relaxed for such types, so that safety guarantees for them are the same as in Java

Cannot Understand the Tail-end Insertion of Linked List in Kotlin [duplicate]

According to the Kotlin docs, the ?. operator represents a 'safe call', meaning that if it's used in a chain of method calls, the entire chain will return null if the value of whatever it's used on is null.
But what about if it's used on the left side of an assignment? Since the left side isn't the side that's 'returning' anything it seems like it probably has a different effect. Here's an example of what I'm talking about:
val myObj = SomeObj()
myObj?.property = SomeClass.someFunc() // What does ?. do in this context?
It means that if one of the safe calls on the left-hand side fails (i.e. its receiver is null), then the whole assignment is skipped, and the expression on the right-hand side is not evaluated at all.
val nullable: Container? = null
nullable?.x = f() // f is not called
(runnable demo)
I'm seeing a fun question & answer in Kotlin just now. Even if the answer is very nice, but I want to clarify it in more detailed.
The assignment expression below:
myObj?.property = SomeClass.someFunc()
is transformed to Java bytecode by Kolin as below:
val it = myObj;
if(it != null){
it.property = SomeClass.someFunc();
}
so there is no problem in multiple threads. It still works fine and I have tested it on github. But it will result in the Thread Interference problem, which means it will modify the property on different references when myObj is changed.
Except the assignment expression can be short-circuited, others also can be short-circuited. For example:
val array:Array<Any>? = null;
// v--- short-circuited
array?.set(0,SomeClass.someFunc());
// ^--- never be called

When working with Java libraries in Kotlin, is it more idiomatic to use ? or !! on method return values?

I'm new to Kotlin and there's a common pattern that I'm not sure how to deal with most correctly. Take this code, for example, which doesn't compile:
git_repo?.add().addFilepattern()
add() is a call in the JGit library which is purely Java, so its return type is AddCommand!.
I have two options:
git_repo?.add()!!.addFilepattern("test.txt")
and
git_repo?.add()?.addFilepattern("test.txt")
Both work fine and given that
I don't know the intricacies of the library implementation,
the documentation of the JGit library doesn't specify whether add() can return null, and
within this context I'd typically expect add() to not return a null
Which version is more idiomatically correct to write in Kotlin? It seems that this would be a fairly common issue to deal with since basically every non-Kotlin library would introduce this issue.
I would use the ?. safe operator and then put your own exception at the end after an ?: Elvis operator. This way you get a message that is meaningful. Using just !! isn't a very helpful message to someone down the road who has no idea what the intricacies were either.
val cmd = gitRepo.add()?.addFilepattern("test.txt") ?: throw IllegalStateException("assert: gitRepo.add() returned an unexpected null")
cmd.doSomething() // never is null guaranteed
If the value is every null you will have a custom error.
assert: gitRepo.add() returned an unexpected null
And after this line, you will not have to null check because the result of the expression is guaranteed never to be null.
If you inspect the code of the other library and ensure it would never ever be null no matter what, then a !! is appropriate. But if not sure, do one better with the custom message.
Note I dropped the first ?. from your example because I'm assuming git_repo itself is not nullable. Plus I renamed it not to have an underscore which isn't normal Kotlin naming convention.
If you are sure that git_repo will always return a value!! is fine in that case.
It is ugly but !! will always be there when you use Java libraries, and you can't avoid it.
The only reason i would use git_repo?.add()?.addFilepattern("test.txt"), would be if you are returning a value, and you want the value to be nullable so that your calling method can handle the nullable.
fun nullableMethod(): string? {
return git_repo?.add()?.addFilepattern("test.txt")
}
fun callingMethod() {
if(this.nullableMethod() != null) {
}
//Else
}
If you are guaranteed it is never going to null, use !!

Immutable val null check inside extension function

When I have an immutable val optional, the compiler tracks the information about the check I performed for null and can treat the variable as non null and call it directly inside the if condition.
val s: String? = "test"
if (s != null) {
s.startsWith("3") // This works
}
if (!s.isNullOrEmpty()) {
s.startsWith("3") // Not working
}
Is it possible to make that check in an extension function and keep the compiler aware of it?
This is not yet available in Kotlin.
There is a feature called "Contracts" which is currently developed at JetBrains (https://discuss.kotlinlang.org/t/status-of-kotlin-internal-contracts/6392) – it's similar to what they've done with their own #Contract annotation for Java code, but will have support from the compiler.
However, it's in early stages and there is no release date yet.

What does ?. mean in Kotlin when used on the left side of an assignment?

According to the Kotlin docs, the ?. operator represents a 'safe call', meaning that if it's used in a chain of method calls, the entire chain will return null if the value of whatever it's used on is null.
But what about if it's used on the left side of an assignment? Since the left side isn't the side that's 'returning' anything it seems like it probably has a different effect. Here's an example of what I'm talking about:
val myObj = SomeObj()
myObj?.property = SomeClass.someFunc() // What does ?. do in this context?
It means that if one of the safe calls on the left-hand side fails (i.e. its receiver is null), then the whole assignment is skipped, and the expression on the right-hand side is not evaluated at all.
val nullable: Container? = null
nullable?.x = f() // f is not called
(runnable demo)
I'm seeing a fun question & answer in Kotlin just now. Even if the answer is very nice, but I want to clarify it in more detailed.
The assignment expression below:
myObj?.property = SomeClass.someFunc()
is transformed to Java bytecode by Kolin as below:
val it = myObj;
if(it != null){
it.property = SomeClass.someFunc();
}
so there is no problem in multiple threads. It still works fine and I have tested it on github. But it will result in the Thread Interference problem, which means it will modify the property on different references when myObj is changed.
Except the assignment expression can be short-circuited, others also can be short-circuited. For example:
val array:Array<Any>? = null;
// v--- short-circuited
array?.set(0,SomeClass.someFunc());
// ^--- never be called