Why the variable can't be initialized correctly in inline function as in java? - variables

We know the lambda body is lazily well, because if we don't call the lambda the code in the lambda body is never be called.
We also know in any function language that a variable can be used in a function/lambda even if it is not initialized, such as javascript, ruby, groovy and .etc, for example, the groovy code below can works fine:
def foo
def lambda = { foo }
foo = "bar"
println(lambda())
// ^--- return "bar"
We also know we can access an uninitialized variable if the catch-block has initialized the variable when an Exception is raised in try-block in Java, for example:
// v--- m is not initialized yet
int m;
try{ throw new RuntimeException(); } catch(Exception ex){ m = 2;}
System.out.println(m);// println 2
If the lambda is lazily, why does Kotlin can't use an uninitialized variable in lambda? I know Kotlin is a null-safety language, so the compiler will analyzing the code from top to bottom include the lambda body to make sure the variable is initialized. so the lambda body is not "lazily" at compile-time. for example:
var a:Int
val lambda = { a }// lambda is never be invoked
// ^--- a compile error thrown: variable is not initialized yet
a = 2
Q: But why the code below also can't be working? I don't understand it, since the variable is effectively-final in Java, if you want to change the variable value you must using an ObjectRef instead, and this test contradicts my previous conclusions:"lambda body is not lazily at compile-time" .for example:
var a:Int
run{ a = 2 }// a is initialized & inlined to callsite function
// v--- a compile error thrown: variable is not initialized yet
println(a)
So I only can think is that the compiler can't sure the element field in ObjectRef is whether initialized or not, but #hotkey has denied my thoughts. Why?
Q: why does Kotlin inline functions can't works fine even if I initializing the variable in catch-block like as in java? for example:
var a: Int
try {
run { a = 2 }
} catch(ex: Throwable) {
a = 3
}
// v--- Error: `a` is not initialized
println(a)
But, #hotkey has already mentioned that you should using try-catch expression in Kotlin to initializing a variable in his answer, for example:
var a: Int = try {
run { 2 }
} catch(ex: Throwable) {
3
}
// v--- println 2
println(a);
Q: If the actual thing is that, why I don't call the run directly? for example:
val a = run{2};
println(a);//println 2
However the code above can works fine in java, for example:
int a;
try {
a = 2;
} catch (Throwable ex) {
a = 3;
}
System.out.println(a); // println 2

Q: But why the code below also can't be working?
Because code can change. At the point where the lambda is defined the variable is not initialized so if the code is changed and the lambda is invoked directly afterwards it would be invalid. The kotlin compiler wants to make sure there is absolutely no way the uninitialized variable can be accessed before it is initialized, even by proxy.
Q: why does Kotlin inline functions can't works fine even if I initializing the variable in catch-block like as in java?
Because run is not special and the compiler can't know when the body is executed. If you consider the possibility of run not being executed then the compiler cannot guarentee that the variable will be initialized.
In the changed example it uses the try-catch expression to essentially execute a = run { 2 }, which is different from run { a = 2 } because a result is guaranteed by the return type.
Q: If the actual thing is that, why I doesn't call the run directly?
That is essentially what happens. Regarding the final Java code the fact is that Java does not follow the exact same rules of Kotlin and the same happens in reverse. Just because something is possible in Java does not mean it will be valid Kotlin.

You could make the variable lazy with the following...
val a: Int by lazy { 3 }
Obviously, you could use a function in place of the 3. But this allows the compiler to continue and guarantees that a is initialized before use.
Edit
Though the question seems to be "why can't it be done". I am in the same mind frame, that I don't see why not (within reason). I think the compiler has enough information to figure out that a lambda declaration is not a reference to any of the closure variables. So, I think it could show a different error when the lambda is used and the variables it references have not been initialized.
That said, here is what I would do if the compiler writers were to disagree with my assessment (or take too long to get around to the feature).
The following example shows a way to do a lazy local variable initialization (for version 1.1 and later)
import kotlin.reflect.*
//...
var a:Int by object {
private var backing : Int? = null
operator fun getValue(thisRef: Any?, property: KProperty<*>): Int =
backing ?: throw Exception("variable has not been initialized")
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) {
backing = value
}
}
var lambda = { a }
// ...
a = 3
println("a = ${lambda()}")
I used an anonymous object to show the guts of what's going on (and because lazy caused a compiler error). The object could be turned into function like lazy.
Now we are potentially back to a runtime exception if the programmer forgets to initialize the variable before it is referenced. But Kotlin did try at least to help us avoid that.

Related

What does "lazy" mean with this code in Kotlin?

What is this code line doing?
fun<T:x>a.b(y: Int)=lazy{u.v<T>(y)}
I do not know what is 'lazy' doing or is 'lazy' something special in Kotlin.
fun<T:x>a.b(y: Int)=lazy{u.v(y)}
Let's break this down. First, let's reformat for readability :)
fun <T: x> a.b(y: Int) = lazy { u.v<T>(y) }
Now, let's go piece by piece.
fun means we're declaring a new method.
<T:x> means this is a generic method operating on type T where T is constrained to be of type x.
a.b means this is an extension function named b on type a.
(y: Int) means that the defined function b takes a single argument named y of type Int.
= is expression body syntax - shorthand for returning a short line of code. This means that a.b will return the value that is the result of evaluating lazy { }
lazy is a Kotlin standard library function that delays the evaluation of the function provided to it until it's needed and then caches the result. The return value of this function is actually a type Lazy that wraps the provided function.
{ u.v<T>(y) } is the function that will be executed by the Lazy object when it's value is obtained the first time and the return value of u.v<T>(y) will be saved as the lazy object's value.
Phew! So what does that mean? Let's look at an example. Suppose we add a print statement to the function to see when it's called.
fun <T: x> a.b(y: Int) = lazy {
println("Executing 'b'")
u.v<T>(y)
}
Now if you tried to use it:
fun main() {
val a = A<T>() // Assume some type T
val lazyObject = a.b<T>(42) // Call the extension method that returns a `Lazy`
// Get the value from the lazy object - prints "Executing 'b'",
// executes `u.v<T>(y)`, caches the result, returns it - then print it
println(lazyObject.value)
// Get the value from the lazy object again. This time, DOES NOT print
// "Executing 'b'", DOES NOT execute `u.v<T>(y)`, and just returns the
// result that was already computed and cached, then print it
println(lazyObject.value)
}
So, in summary, the code you posted is creating an extension method that returns a Lazy object that, when queried for its value, executes the lambda it's initialized with and caches that result for later use.
Hope that helps!

Kotlin Higher Order Function in ViewModel

I am new to kotlin , so need help to understand the code ,I went to a blogs and found something like this and implemented in my code , code work perfect but i can't understand the following things .
Basically , I got lost in how lazyDefferd function , how it's works internally.
a. How generic T is passed .
b. What it mean by this CoroutineScope.() as i know this is input that i need to pass from the ViewModel but how it's getting pass i can't understand .
interface MovieRepository {
suspend fun getTopRatedMovie(page:Int): LiveData<out List<TopRatedMovieEntity>>
}
ViewModel :
class TopRatedMovieViewModel(movieRepository: MovieRepository):ViewModel() {
val topMovie by lazyDefferd{
movieRepository.getTopRatedMovie(1)
}
}
fun <T> lazyDefferd(block:suspend CoroutineScope.()->T):Lazy<Deferred<T>>{
return lazy {
GlobalScope.async(start = CoroutineStart.LAZY) {
block.invoke(this)
}
}
}
a. How generic T is passed.
You can pass it explicitly, e.g.:
val myLazyDeffered = lazyDefferd<SomeType> {
// …
}
But the compiler can usually infer the type, so it's more usual to omit it (unless there's a reason why it's not clear from the code).  That's what's happening in your topMovie example: the compiler knows what type the lambda returns, so it infers T from that.
(As you've probably already noted, lazyDefferd() also takes a value parameter, but since it's the last parameter and a lambda, Kotlin lets you omit the parens.)
b. What it mean by this CoroutineScope.()
That's a function literal with receiver.  The lambda that you pass to block will behave as if it's an extension method on the CoroutineScope class: inside the lambda, this will refer to a CoroutineScope instance.  It's similar to passing the instance as a parameter to the lambda (and in this case, that's how it's called), but the syntax is more concise.

What is the difference between require and assert?

With Kotlin 1.3 came a new feature, contracts, and with them the function require(), but it seems pretty similar to assert(). Here is what their KDoc says:
require(value: Boolean): Throws an IllegalArgumentException if the value is false.
assert(value: Boolean): Throws an AssertionError if the value is false and runtime assertions have been enabled on the JVM using the -ea JVM option.
So when should I use require() and when should I use assert()?
require and assert work differently. For this, you need to dive into the code.
assert(condition) calls a different method internally, which is where you see the actual code:
#kotlin.internal.InlineOnly
public inline fun assert(value: Boolean, lazyMessage: () -> Any) {
if (_Assertions.ENABLED) {
if (!value) {
val message = lazyMessage()
throw AssertionError(message)
}
}
}
AFAIK, this ties to the -ea flag; if -ea isn't present (or disabled), assert will not throw an exception.
As a result, this will not compile:
fun something(string: String?){
assert (string != null)
nonNull(string) // Type mismatch
}
fun nonNull(str: String){}
This is where require comes in. require(condition) also calls a different method under the hood. If you replace assert with require, you'll see that smart cast will successfully cast it as non-null, because require is guaranteed to throw an exception if the condition fails.
#kotlin.internal.InlineOnly
public inline fun require(value: Boolean, lazyMessage: () -> Any): Unit {
contract {
returns() implies value
}
if (!value) {
val message = lazyMessage()
throw IllegalArgumentException(message.toString())
}
}
The boolean-only function does the contract too, then calls that method if the contract fails.
Contracts are new, and I am not entirely sure how they work, but this is how I understand it:
The implies keyword is an infix fun; what this does is that it tells the compiler the condition is true if it returns from the method. This helps with auto-casting, like in the example I mentioned earlier. It doesn't actually cause the method to return (or at least that's what my current testing points to), but it's for the compiler.
It's also readable: returning implies condition is true
That's the contact part: the exception here is always thrown, as you can see by the condition. require uses if(!value), where as assert checks if(_Assertions.ENABLED && !value).
This isn't the only use for require though. It can also be used for validation of arguments. I.e. if you have this:
operator fun get(index: Int) : T {
if (index < 0 || index >= size)
throw IllegalArgumentException("Index out of range")
// return here
}
You could replace it with:
operator fun get(index: Int) : T {
require (index >= 0 && index < size) { "Index out of range" }
// return here
}
There are a lot different uses for this, but these are just some examples.
What this means:
assert is like in Java; it is only triggered if assertions are enabled. Using it does not guarantee the condition is met.
require always works, regardless of VM flags
Which means require can be used to help the compiler with i.e. smart cast, and it's better to use than assert for making sure arguments are valid. And since it also works regardless of VM flags, it can be used outside debugging cases, as forpas mentioned. If you're making a library written in Kotlin, you can replace argument checking with manual throwing with require, and it will still work. Obviously, this assumes Kotlin 1.3.0, but that's beside the point.
And it can be used internally to ensure smart cast works as expected, but throw an exception if the condition isn't met.
To answer your question though:
Use require when you want to to argument checking, even if it's in production.
Use assert if you're doing local debugging, and have the -ea flag enabled.
Let's say you want a function to calculate n! (factorial) like this:
fun factorial(n: Long): Long {
require(n >= 0) { "Number must not be negative" }
// code
}
In this case require() checks the validity of the argument passed to the function and throws an IllegalArgumentException if the argument is not what it's supposed to be and for debugging you also have the explanatory message.
On the other hand assert() can be used anywhere in your code to make your own specialized checks if runtime assertions have been enabled.
There is also
check(Boolean) throws IllegalStateException when its argument is false,
which is used to check object state.
So each of the above has its own place in your code and you can use it if you find it useful.

Compilation error: Smart cast to '<type>' is impossible, because '<variable>' is a local variable that is captured by a changing closure

To simplify my real use case, let's suppose that I want to find the maximum number in a list:
var max : Int? = null
listOf(1, 2, 3).forEach {
if (max == null || it > max) {
max = it
}
}
However, compilation fails with the following error:
Smart cast to 'Int' is impossible, because 'max' is a local variable that is captured by a changing closure
Why does a changing closure prevent smart cast from working in this example?
In general, when a mutable variable is captured in a lambda function closure, smart casts are not applicable to that variable, both inside the lambda and in the declaring scope after the lambda was created.
It's because the function may escape from its enclosing scope and may be executed later in a different context, possibly multiple times and possibly in parallel. As an example, consider a hypothetical function List.forEachInParallel { ... }, which executes the given lambda function for each element of the list, but in parallel.
The compiler must generate code that will remain correct even in that severe case, so it doesn't make an assumption that the value of variable remains unchanged after the null check and thus cannot smart cast it.
However, List.forEach is quite different, because it is an inline function. The body of an inline function and the bodies of its functional parameters (unless the parameter has noinline or crossinline modifiers) are inlined at the call site, so the compiler could reason about the code in a lambda passed as an argument to inline function as if it was written directly in the calling method body making the smart cast possible.
It could, but currently, it doesn't. Simply because that feature is not implemented yet. There is an open issue for it: KT-7186.
Thanks to Ilya for the detailed explanation of the problem!
You can use the standard for(item in list){...} expression like this:
var max : Int? = null
val list = listOf(1, 2, 3)
for(item in list){
if (max == null || item > max) {
max = item
}
}
This looks like a compiler bug to me.
If the inline lambda parameter in forEach were marked as crossinline then I would expect a compilation error because of the possibility of concurrent invocations of the lambda expression.
Consider the following forEach implementation:
inline fun <T> Iterable<T>.forEach(crossinline action: (T) -> Unit): Unit {
val executorService: ExecutorService = ForkJoinPool.commonPool()
val futures = map { element -> executorService.submit { action(element) } }
futures.forEach { future -> future.get() }
}
The above implementation would fail to compile without crossinline modifier. Without it, the lambda may contain non-local returns which means it cannot be used in a concurrent fashion.
I suggest creating an issue: Kotlin (KT) | YouTrack.
The problem is that foreach creates multiple closures, each of which access the same max which is a var.
What should happen if max were set to null in another of the closures after the max == null check but before it > max?
Since each closure can theoretically work independently (potentially on multiple threads) but all access the same max, you can't guarantee it won't change during execution.
As this is in the top results for the error Smart cast to '<type>' is impossible, because '<variable>' is a local variable that is captured by a changing closure here is a general solution that worked for me (even if the closure is not inlined):
Sample showing this error:
var lastLine: String? = null
File("filename").useLines {
lastLine = it.toList().last()
}
if(lastLine != null) {
println(lastLine.length) // error! lastLine is captured by the useLines closure above
}
Fix: Create a new variable that is not captured by the closure:
var lastLine: String? = null
File("filename").useLines {
lastLine = it.toList().last()
}
val finalLastLine = lastLine
if(finalLastLine != null) {
println(finalLastLine.length)
}

How do I initialize a final field in Kotlin?

Let's say I declared a final field with private final String s (Java) or val s (Kotlin). During initialization I want to initialize the field with the result of a call to a remote service. In Java I would be able to initialize it in the constructor (e.g. s = RemoteService.result()), but in Kotlin I can't figure out how to do that because as far as I can tell the field has to be initialized in the same line it's declared. What's the solution here?
You can set val value in init block:
class MyClass {
val s: String
init {
s = "value"
}
}
You can also initialize the value with by lazy the value will be initialized the first time it is referred. An example
val s by lazy { RemoteService.result() }
kotlin will guess the type of s from the return type of the expression.
You can use run:
class MyClazz {
val prop = run {
// do stuff
// do stuff again
123 // return expression
}
}
From the docs (emphasis is mine):
Besides calling run on a receiver object, you can use it as a non-extension function. Non-extension run lets you execute a block of several statements where an expression is required.
It has been possible to do it simply like this since the very first official stable release of Kotlin:
class MyClass {
val s = RemoteService.result()
}