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

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

Related

Why does `EffectScope.shift` need the type parameter `B`?

The move to the new continuations API in Arrow brought with it a handy new function: shift, in theory letting me get rid of ensure(false) { NewError() } or NewError().left().bind() constructs.
But I'm not sure how to properly use it. The documentation states that it is intended to short-circuit the continuation, and there are no conditionals, so it should always take the parameter, and (in either parlance) "make it a left value", and exit the scope.
So what is the type parameter B intended to be used for? It determines the return type of shift, but shift will not return. Given no more context, B can not be inferred, leading to this kind of code:
val res = either {
val intermediate = mayReturnNull()
if (intermediate == null) {
shift<Nothing>(IntermediateWasNull())
}
process(intermediate)
}
Note the <Nothing> (and ignore the contrived example, the main point is that shifts return type can not be inferred – the actual type parameter does not even matter).
I could wrap shift like this:
suspend fun <L> EffectScope<L>.fail(left: L): Nothing = shift(left)
But I feel like that is missing the point. Any explanations/hints would be greatly appreciated.
That is a great question!
This is more a matter of style, ideally we'd have both but they conflict so we cannot have both APIs available.
So shift always returns Nothing in its implementation, and so the B parameter is completely artificial.
This is something that is true for a lot of other things in Kotlin, such as object EmptyList : List<Nothing>. The Kotlin Std however exposes it as fun <A> emptyList(): List<A> = EmptyList.
For Arrow to stay consistent with APIs found in Kotlin Std, and to remain as Kotlin idiomatic as possible we also require a type argument just like emptyList. This has been up for discussion multiple times, and the Kotlin languages authors have stated that it was decided too explicitly require A for emptyList since that results in the best and most consistent ergonomics in Kotlin.
In the example you shared I would however recommend using ensureNotNull which will also smart-cast intermediate to non-null.
Arrow attempts to build the DSL so that you don't need to rely on shift in most cases, and you should prefer ensure and ensureNotNull when possible.
val res = either {
val intermediate = mayReturnNull()
ensureNotNull(intermediate) { IntermediateWasNull() }
process(intermediate) // <-- smart casted to non-null
}

Kotlin "let{}" Doesn't Provide Smart Cast

Just learned Kotlin Nullable type and let{} function which replaces the if (xx != null) {} operation.
But one thing I am confused is that, we all know and I Think the Complier Should Know that when we use let{}, the variable/object who is calling this function is possiblly null, however the complier still requires me to add the safe call operator "?" after the variable name instead of providing Smart Cast like it does in if (xx != null) {}. Why?
My piece of code:
fun main() {
var number1: Int? = null
//val number2 = number1.let { it + 1 } ?: 10 //doesn't work, not quite "smart"
val number2 = number1?.let { it + 1 } ?: 10 //works, must have "?"
println(number1)
println(number2)
}
You've already got answers in the comments, but just to explain the ? thing...
Kotlin lets you make null-safe calls on nullable variables and properties, by adding ? before the call. You can chain this too, by doing
nullableObject?.someProperty?.someFunction()
which evaluates nullableObject, and if it's non-null it evaluates the next bit, otherwise the whole expression evaluates to null. If any part of the chain evaluates as null, the whole expression returns null.
So it has this short-circuiting effect, and you can use the elvis "if null" operator to create a default value if you can't evaluate the whole chain to a non-null result:
nullableObject?.nullableProperty?.someFunction() ?: defaultAction()
and once you introduce the null check in the chain, you have to add it for every call after that - it's basically propagating either the result of the previous bit, or the null it resolved to, so there's a null check at each step
The let block is just a scope function - you use it on a value, so you can run some code either using that value as a parameter or a receiver (a variable or this basically). It also has the side effect of creating a new temporary local variable holding that value, so if the original is a var it doesn't matter if that value changes, because your let code isn't referring to that variable anymore.
So it's useful for doing null checks one time, without worrying the underlying value could become null while you're doing stuff with it:
nullableVar?.let { it.definitelyIsNotNull() }
and the compiler will recognise that and smart cast it to a non-null type. An if (nullableVar != null) check can't guarantee that nullableVar won't be null by the time the next line is executed.

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 is the difference between not-null checks in Kotlin?

There are some ways to fulfill a null-checking in Kotlin:
1.
if(myVar != null) {
foo(myVar)
}
2.
myVar?.let {
foo(it)
}
3.
myVar?.run {
foo(this)
}
What are the difference between these ways?
Are there any reasons (performance, best practice, code style etc.) why I should prefer on way over the other?
!! is to tell the compiler that I am sure the value of the variable is not null, and if it is null throw a null pointer exception (NPE) where as ?. is to tell the compiler that I am not sure if the value of the variable is null or not, if it is null do not throw any null pointer.
Another way of using a nullable property is safe call operator ?.
This calls the method if the property is not null or returns null if that property is null without throwing an NPE (null pointer exception).
nullableVariable?.someMethodCall()
All three code are behave same null check in operation-wise.
?. is used for chain operations.
bob?.department?.head?.name // if any of the properties in it is null it returns null
To perform a chain operation only for non-null values, you can use the safe call operator together with let
myVar?.let {
foo(it)
}
the above code is good for code style and performance
more details refer Null Safety
The ways 2 and 3 are more idiomatic for Kotlin. Both functions are quite similar. There is little difference with argument passing.
For example, we have a nullable variable:
var canBeNull: String? = null
When you working with T.run you work with extension function calling and you pass this in the closure.
canBeNull?.run {
println(length) // `this` could be omitted
}
When you call T.let you can use it like lambda argument it.
canBeNull?.let {
myString -> println(myString.length) // You could convert `it` to some other name
}
A good article about Kotlin standard functions.
All three are roughly equivalent.
The if case is more like most other languages, and so many developers may find it easier to read.
However, one difference is that the if case will read the value of myVar twice: once for the check, and again when passing it to foo(). That makes a difference, because if myVar is a property (i.e. something that could potentially be changed by another thread), then the compiler will warn that it could have been set to null after the check. If that's a problem (e.g. because foo() expects a non-null parameter), then you'll need to use one of the other cases.
For that reason, the let case has become fairly common practice in Kotlin. (The run case does just about the same thing, but for some reason isn't as popular for this sort of thing. I don't know why.)
Another way around it is to assign myVar to a temporary value, test that, and then use that. That's also more like other languages, but it's more verbose; many people prefer the conciseness of the let case — especially when myVar is actually a complicated expression.
The examples in your question don't show the true reason to decide.
First of all, since you're not using the return value of foo, you should use neither let nor run. Your choice is between also and apply.
Second, since you already have the result you want to null-check in a variable, the difference fades. This is a better motivating example:
complexCall(calculateArg1(), calculateArg2())?.also {
results.add(it)
}
as opposed to
val result = complexCall(calculateArg1(), calculateArg2())
if (result != null) {
results.add(result)
}
The second example declares an identifier, result, which is now available to the rest of the lexical scope, even though you're done with it in just one line.
The first example, on the other hand, keeps everything self-contained and when you go on reading the rest of the code, you are 100% confident that you don't have to keep in mind the meaning of result.
Kotlin have new features with NullPoint-Exception as Compare to Java.
Basically When we do Coding in Java , then we have to Check with !! in every Flied.
But in Kotlin, it is Easy way to Implement First
as Like,
Suppose, in Kotlin
var response:Json?=Null
response:Json?.let {
this part will handle automatic if response is Not Null....then this Block start Executing }?.run {
This is Nullable But, where we Can put Warring } So, I am Suggest you Guys to Start Work in Kotlin with this Features Provided by Kotlin.
(Flied)?.let { Not Null Value Comes Under }?.run{ Null Value Code }
This will Handle to NullPoint Exception or Protect You App for Crash
What you want to achieve
What you want to achieve is that the Kotlin compiler does a smart cast on the variable you are working with.
In all of your three examples, the compiler can do that.
Example:
if(myVar != null) {
foo(myVar) // smart cast: the compiler knows, that myVar can never be null here
}
The choice
Which one of the options to use, is really a matter of style. What you should not do is mix it up to often. Use one and stick to it.
You don't need to worry about performance since let and run are inlined (see inline function). This means that their code (body) is copied to the call site at compile time so there is no runtime overhead.

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