A while ago I spent quite some time trying to figure out why a simple block of Kotlin code didn't want to do what I was wanting it to do. After numerous attempts on rewriting my code, thinking that it must've been a mistake on my end, I decided to dive into the generated code to try and figure out what happens in the background.
The topic is
run, the 2 inline functions from the standard Kotlin library available to developers. The way I thought that
run work in combination was in a similar way to a classical if/else statement. So I started and continued using them like that, until a ran into a wall when I was implementing something in one project.
Let's take a look at what the issue is:
So in this example we have a simple Kotlin class with 2 nullable variables of which one is already defined with a value. Now, looking at the code the question is, what would be printed in the console if I would to call doSomeAwesomePrinting()?
If you said nothing, sorry to say, that would be incorrect. The correct answer would be "awesome output 1".
I know, it doesn't make any sense, right?
What's going on here? Let's decompile this simple example into Java and see what happened:
Ok ok, now this makes sense, I mean the code. We can clearly see that this function will execute to the end and print the "awesome output 1" at the end because the second variable was indeed null and it wouldn't do the return.
Now let's take a quick look at one more example and find a solution together in the end.
In this next example we will only change one thing, and that is to add the
run block, or the
elvis operator on the second variable
What do you think would be printed if the doSomeAwesomePrinting() function was called again?
Yes, it will print out "awesome output 3"!
Now this one does what you'd want it to, it feels like a real if/else statement. And the Java decompiled code does confirm that as well:
Thanks to Danny for mentioning it, it would seem that a different Kotlin inline function would do the trick.
Danny Preussler #blacklivesmatter@preusslerberlin@vlazdra it works with `apply`.
The problem seems that `let` returns the outcome of the block, which is null, which leads to the elvis block getting called 🤯15:13 PM - 26 Jul 2020
So after trying out what Danny suggested, it worked! Now let's take a look at what happens under the hood when using the
apply Kotlin inline function on the same examples from before.
Output? Nothing actually. Let's see what the decompiled code looks like with this example and try to understand the mechanics:
After decompiling the same block but with
apply we now have a different Java code, that does not output anything as one would expect.
And finally let's look at one more example where we would catch the null value of the inner variable with the elvis operator and the
Anyone interested in the output? The console will have "awesome output 3" printed out since the awesomeVar2 is null. Let's dive into the Java decompiled code to get a better understand what happened here:
A bit more complex than the previous examples but approximately the same result, the console will output "awesome output 3" as it was intended to, and we know have a better picture as to why and how.
In part 2 of this topic, we will dive deeper on how the Kotlin compiler compiles the inline functions from the standard library and to better understand the behaviour mentioned in this article. So stay tuned.
While you can of course still use the
let inline function normally as you already have, just be careful of the effect mentioned in this article and make sure that your use case works as expected.
It is always fun to discover things like this, to get a better understanding of the tools and languages we are using on a daily basis. By discovering things like this we improve ourselves, but by also sharing it we help others improve themselves as well.
With that, I would like to thank you for reading through to the end of this article. I really hope it gave you some clarity over how the Kotlin code gets generated to Java, and how this specific topic could affect the code you write everyday. If you found this article interesting, please feel free to share it, and give a like bellow.
Note: The decompiled Java code shown in this post is not the exact equivalent to the one that gets generated. I removed the unnecessary code in order to make it shorter and a little bit more readable for the purpose of this article.