Kotlin: Inner scope - This [duplicate] - kotlin

This question already has answers here:
How to reference a lambda from inside it?
(4 answers)
Closed 7 years ago.
I just made use of Kotlins auto refactor and it basically left me with this:
coverView.viewTreeObserver.addOnPreDrawListener {
coverView.viewTreeObserver.removeOnPreDrawListener(this)
true
}
Which does not work. IntelliJ shows me that this refers to the outer class but not to the OnPreDrawListener. Why is that? The kotlin docs say that this always refer to the inner most scope.

To fix your code you can use object expression instead of lambda here:
coverView.viewTreeObserver.addOnPreDrawListener(object : ViewTreeObserver.OnPreDrawListener {
override fun onPreDraw(): Boolean {
coverView.viewTreeObserver.removeOnPreDrawListener(this)
return true
}
})
this expression in function expression (and the lambda you pass to the addOnPreDrawListener method is function expression) allows you to access lambda's closure, i.e. variables declared in its outermost scope, not the lambda itself.

Related

Kotlin construction: function call with additional body - what such construction means or how it is called (if I want to look it up in the docs)?

I am seeing the Kotlin code:
navController.navigate("sales_order/" + it.toString()) {
popUpTo(navController.graph.findStartDestination().id) {
saveState = true
}
launchSingleTop = true
restoreState = true
}
which I can describe as "function call" (navController.navigate) "with additional body" ({...}). How such construction is called (if I want to look it up in the docs) and what does it mean?
When I checked the type of navController.navigate(...) args, then there are 2 arguments. The first argument - string - is provided in () and I am trying to guess, that everything inside {...} is the content for the second argument which has type NavOptionsBuilder in this case. So, I can guess that NavOptionsBuilder has 3 arguments: 1 function call popUpTo that returns some object and 2 named arguments (launchSingleTop, restoreState) which are Boolean type.
Am I deciphering this construction right - just another way of passing arguments - or is there something deeper?
Am I deciphering this construction right
Almost. You got the beginning right, but the end is not exactly correct.
Let's start with what you got right, and throw in some vocabulary here for posterity. Indeed, you seem to be using the overload of navigate that takes 2 arguments: a string route and a builder function.
Functions in kotlin can be passed in multiple ways, but the most common (and the one used here) is passing a lambda expression. Because the syntax for lambda expressions is based on braces ({ ... }), it makes it look like blocks of code, so the Kotlin language went one step further and allowed to pass lambda expressions outside of the parentheses of the function call when the lambda is the last argument. The reason for this is exactly to allow this kind of constructions which look like their own configuration language. This is what is usually referred to as DSLs (Domain Specific Languages).
Now about what you got wrong:
So, I can guess that NavOptionsBuilder has 3 arguments
Not really. NavOptionsBuilder is the receiver of the function that is passed as the second argument of navigate. This means that, within the lambda that you pass, a NavOptionsBuilder instance is implicitly available as this.
This, in turn, means that you can access methods and properties of NavOptionsBuilder within that lambda block. This is what popUpTo, launchSingleTop, and restoreState are: methods and properties of NavOptionsBuilder - not "arguments".
You can find more general info about this here.

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

Initializing a field member in Kotlin that is a function

New to Kotlin, I have seen this code:
val myModule : Module = module {
viewModel { MyViewModel(get()) }
single { MyRepository() }
}
Looking at the Kotlin docs, it isn't clear to me what the braces mean after "module". Is module a function and the braces are used to initialize the function? If this is true, can you point me to the part in the Kotlin documentation that indicates this? I can't find anything in the docs that shows an example of this. Here is the link:
https://kotlinlang.org/docs/reference/properties.html
Note that your example seems like Koin code.
In a more general sense:
In kotlin when the last parameter of a function is another function ( see Higher order functions) you can put it outside the parenthesis, and if it is the only (non optional) parameter you can omit the parenthesis enterily.
In your example module viewModel and single are functions that take another function as their only parameter, this way you can pass the lambda defining this paramter directly without any parenthesis.
The braces mean that the module function receives a lambda as a parameter. http://kotlinlang.org/docs/reference/lambdas.html#passing-a-lambda-to-the-last-parameter

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) }
}

Why do Lambda expressions behave differently for Kotlin and Java classes? [duplicate]

This question already has answers here:
Passing a listener object as a function parameter in kotlin
(2 answers)
Closed 5 years ago.
Why can I use Lambda for the class java.lang.Thread, but not for MyThread?
interface MyRunnable{
fun run()
}
class MyThread(runnable : MyRunnable){
}
fun test(){
Thread({}) // All Alright
MyThread({}) //Exception. Type mismatch <<-- Why ?
}
Link to check this example: https://try.kotlinlang.org/#/UserProjects/tbs79qfkh50psp7r3qrdrinrmt/sfkpjq1bjvg4r6d5rmnu6mp4a8
From the docs on SAM conversions:
Note that this feature works only for Java interop; since Kotlin has proper function types, automatic conversion of functions into implementations of Kotlin interfaces is unnecessary and therefore unsupported.
In other words, using { ... } syntax is only supported for calls to Java. The public rationale is that you could do either of:
Have your MyThread constructor take a first-class function type as a parameter.
Use an object expression:
MyThread(object : MyRunnable {
override fun run() {}
})
This is obviously fairly verbose. However, according to this Kotlin ticket, the lambda syntax is actually only part of the Java interop, not part of the core language, so would take some careful design to do anything more.