kotlin if (bar == null) vs. bar ?: run [closed] - kotlin

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
Here is sample
if (bar == null) {
// do something
}
vs.
bar ?: run {
// do something.
}
which one is best practice?
what is mutating property?
first one dosen't work with mutating property?

which one is best practice?
As pointed out by Oliver, the intent is most clear when using if(bar == null). This is also the approach used in official Kotlin documentation under Checking for null conditions.
Though I don't suggest it in this case, Kotlin allows you to do neat things like this:
inline fun whenNull(input: Any?, block: () -> Unit) {
if(input == null) block()
}
Which would allow you to rewrite if(bar == null) as:
whenNull(bar) {
// Do something
}
what is mutating property?
It's a variable whose value can be changed. Basically, the variable is declared using var and not val.
first one dosen't work with mutating property?
This isn't really relevant to your example because you are checking if(bar == null).
What you are referring to is relevant if you were checking if(bar != null). In this case, if bar is a var, Kotlin can't smart cast it a non-null type since within the body of the if the value of bar could change at any time. This means within the body of the if you'd have to make safe calls on bar (?.), or use !!.
You can work around this by doing the following:
val b = bar
if(b != null)
{
// b has been smart cast to a non-null type
}
Kotlin is able to smart cast b to a non-null type within the body of the if because it is non-mutable (val).
Alternatively, you can use a safe call and let, which calls the specified function/block with this value as its argument and returns its result. Given the safe call, this is of course non-null.
bar?.let {
// this is bar (non-null)
}

Related

Kotlin function unresolved reference [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 1 year ago.
Improve this question
I'm working on this thing that has some function callings like this:
fun f1(){
// does some stuff
f2();
}
fun f2(){
// does some stuff
f1();
}
This is a simplification of what my code looks like (it doesn't go for an infinity loop). My problem is that it returns the error that f2 is unreferenced. I tried searching this online but the only solutions I saw from people asking where to move the function above the funciton call, but that wouldn't work for me since my other function calls that one as well and moving the f2 above f1 would just make f1 unresolved when f1 is called from f2.
I also tried the function declaration thing c and c++ has but it lead to errors saying I have ambiguous function definitions and that they're expecting a function body in the function declaration.
Thanks.
I am assuming you are trying to define both functions inside the same local scope and getting an "Unresolved reference" Kotlin compiler error.
If that is your case and you cannot refactor your flow in a better way, then you can declare one of the functions as a nullable variable and assign it later.
Your code would then become
var f2: (() -> Unit)? = null
fun f1() {
// does some stuff
// Option 1: wont get invoked if f2 is null when this line is executed
f2?.invoke()
// Option 2: will always try to get invoked, but if f2 is null when this line is executed,
// it will throw a NullPointerException
f2!!.invoke()
}
f2 = {
// does some stuff
f1()
}

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

What different StringBuilder and StringBuilder! in kotlin? [duplicate]

This question already has answers here:
Single exclamation mark in Kotlin
(7 answers)
Example of when should we use run, let, apply, also and with on Kotlin
(6 answers)
Closed 2 years ago.
In the code below. I found in Intellij Idea compiler that val a and val b by default are "val a: StringBuilder" & "val b: StringBuilder!"
what is the difference between the two? What's the difference between StringBuilder and StringBuilder! ? Thank you :)
fun main(){
val a = StringBuilder().apply { // by default is val a : StringBuilder
append("Hello ")
append("from me")
}
println(a)
val b = StringBuilder().run { // by default is val b : StringBuilder!
append("Hello ")
append("from me")
}
println(b)
}
The ! indicates a platform type. It means that the compiler can't tell whether the type is nullable or not, because it comes from Java (or another JVM language), which doesn't make the distinction between nullable and non-nullable types, and doesn't have an annotation (#Nullable or #NonNull) to indicate that.
As a result, the compiler won't be able to make its usual null checks, so you should take care.
If you know (from the documentation, or looking at the Java code, or whatever) whether the value could be null or not, it's a good idea to specify the type explicitly (as either nullable with a trailing ?, or non-nullable without).
In this case, the difference is that apply() returns the value it was called on; that's all Kotlin, so the compiler knows its type. However, run() returns the last value in the lambda, which is the result of the last append() call. That method is defined in Java (since StringBuilder is part of the Java standard library), so the compiler can't tell whether it's nullable or not. But it's clear from the documentation that the method simply returns the StringBuilder it was called on, and so cannot be null. So for safety, you could specify an explicit StringBuilder type (i.e. non-nullable) for b.

What is the purpose of 'let' keyword in Kotlin [duplicate]

This question already has answers here:
Example of when should we use run, let, apply, also and with on Kotlin
(6 answers)
Closed 3 years ago.
We can write the code with or without let as follows.
var str = "Hello World"
str.let { println("$it!!") }
OR
var str = "Hello World"
println("$str!!")
What is the Actual use of let?.Is that more memory efficient or more readable?
let is one of Kotlin's Scope functions which allow you to execute a code block within the context of an object. In this case the context object is str. There are five of them: let, run, with, apply, and also. Their usages range from but are not exclusive to initialization and mapping.
They are all very similar but they differ in terms of how the context object is referenced and the value that is returned. In the case of let the context object is referenced by the it keyword as opposed to the this keyword. The return value is whatever is returned from the lambda code block. Other scope functions like apply will return the context object instead.
Because let returns whatever the lambda block evaluates to, it is most suited to performing a mapping of some kind:
var upperStr = str.let { it.toUpperCase()}
apply is a more suited function for what you are doing.
To answer your question as to which code is more preferable, it really depends on what you are using the scope function for. In the above case there is no reason to use let. If you are using IntelliJ it will give a warning saying the call to let is redundant. Readability here is a matter of preference, and may be preferred.
The let function is useful when you wish to perform a null safe operation on an Object by using the the safe call operator ?. When doing this the let code block will only be executed if the object is not null. Another reason to use let is if you need to introduce new variables for the operation but you want to confine them to the scope of the let block. This is true for all scope functions, so I reiterate that let is best used for a mapping operation.
Edit: The let function should incur no additional cost. Normally we would expect the lambda/Code-block to be compiled to a Function object but this is not the case for an inline function in Kotlin for which the compiler will emit code not dissimilar to the second code example you have given. See the documentation for more information.
One of usages you can check nullable types
var str: String? = null
str?.let { println("$it!!") }
it's equal
if (str != null) {
System.out.println(str);
}
in Java, but shorter and more useful
let takes the object it is invoked upon as the parameter and returns the result of the lambda expression.
Kotlin let is a scoping function wherein the variables declared inside the expression cannot be used outside.
One of the examples would be here :
fun main(args: Array<String>) {
var str = "Hello World"
str.let { println("$it!!") }
println(str)
}
You can find more information on Kotlin let function here

What are Local declarations for : variables, functions and classes In Kotlin? [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 4 years ago.
Improve this question
So i started learning kotlin for android development.
But when i get to the visibility topic i met this note stating:
Local declarations
Local variables, functions and classes can not have visibility modifiers.
What are Local declarations in Kotlin ?
I asked you here witch means i already did a search on the internet but the only results i have got they were about java and other programming languages and i don't want to mix up things so i can avoid confusion.
Thanks very much in advance
Local declarations are declarations placed inside a body of a function (or a constructor, an init block, or a property accessor).
These declarations can only be referenced inside the lexical scope where they are declared:
fun foo() {
if (Random().nextInt() % 2 == 0) {
fun bar() {
println("bar")
}
bar() // OK
} else {
bar() // Error: unresolved reference
}
}
Consequently, these declarations can never be used outside the body, and therefore visibility modifiers (which normally control whether a declaration is accessible outside the type or the file) are meaningless for local declarations.
Local declarations can be used for entities that have meaning only inside a body of the function and not anywhere else, or should not be used anywhere else.
An example of a valid use case for local declarations is a data class for intermediate values of a calculation:
fun getAndSaveEmails(people: List<Person>) {
data class PersonWithEmail(
val person: Person,
val email: String
)
val peopleWithEmails = people.map { PersonWithEmail(it, requestEmail(it)) }
peopleWithEmails.forEach { save(it.person, it.email) }
}