Kotlin clarification about # symbol and return postfixes - kotlin

I am confused about the meaning usage of the next syntax.
What does exactly do placing the postfixes "async" and "lazy" after a "return"?
return async
return lazy
What does the "#" symbol mean here?
return#async
return#lazy
return#withContext
About the "#" symbol, does it have a special naming in Kotlin? so I can better locate all the ways to use it in the documentation?
What is the difference between adding # and not using it? so:
"return async" vs "return#async"

What does exactly do placing the postfixes "async" and "lazy" after a "return"?
This is not special syntax in Kotlin with the specific words "async" or "lazy". So it is not really a "postfix for the return keyword". After a space, what follows the return is always the value that you want to return:
return 42 returns the value 42
return async returns the value of the expression async (which is probably a variable that has been declared earlier in the code)
return async { 42 } returns the value of the expression async { 42 }.
The meaning of the expression async { 42 } here is unrelated to the return in itself. You could see the same expression assigned to a variable for instance: val deferred = async { 42 }. async is simply a library function from the kotlinx.coroutines library (it's just my guess by the way, maybe the code you've seen declares variables/functions of this name, but it's hard to tell without more context). Have a look at the doc of the async function here if you're interested.
What does the "#" symbol mean here?
The return keyword by default returns from the closest enclosing function declared with the fun keyword. Lambdas don't count, because they are not declared with fun.
Therefore, return-ing from inside a lambda will by default (without #) return from an enclosing function rather than just the "local" lambda (as opposed to what happens in Java). This is why we call them non-local returns.
Using a qualified return with a label (return#label) allows to change this default behaviour and specify what you want to return from explicitly.
See the doc about return at labels, it contains many examples.
The specific examples you gave:
return#async
return#lazy
return#withContext
would need a bit more context to understand them. But I assume that you have seen them used inside lambdas that are a parameter of async/lazy/withContext function calls. What follows the # here is called an implicit label which tells the compiler that this return is supposed to return from this lambda instead of returning from the closest enclosing fun.
Other notes
Note that the # symbol here is not an annotation like you could see elsewhere like #JvmDefault or #OptIn(...), it is instead a label reference.
Note that both a label and a return value can be combined: return#myLabel 42 returns the value 42 from the function qualified by the label myLabel.

Related

In kotlin what is this syntax: "fun ClassName.funcName(): (Type ) -> Type = {fun body}"

Edited: What and how it work? This is a kotlin dsl language.
fun ClassName.funcName(): (Type ) -> Type = {func body}
um this is one of the implementation I found, and also see the concrete syntax to this link: https://dzone.com/articles/the-complete-custom-gradle-plugin-building-tutoria
private fun CodeLinesExtension.buildFileFilter():
(File) ->
Boolean =
if (fileExtensions.isEmpty()) {
{ true }
} else {
{ fileExtensions.contains(it.extension) } // filter by extension
}
if you CALL this one as a arguments in ".filter(...)", what would happed in the "(File)" syntax, is it automatically receive an arguments?
someFiles.filter(CodeLinesExtension.buildFileFilter()).forEach{...}
There are many things at play here.
fun SomeClass.funcName() is the syntax for declaring extension functions. These are used just like regular methods of the class SomeClass, but can be defined outside of the class, and it's especially useful on classes that you don't control.
The return type of the function you mention is (File) -> Boolean. This expression describes a function type. In this specific case, it is the type of all functions that take a File as single argument, and return a Boolean.
This means that your buildFileFilter() function is an extension function that itself returns a function (File) -> Boolean.
As you can see in the function's body, inside the if statement, there are braces to define the blocks of the if-else ({ ... }), but also braces inside those blocks. This is because Kotlin uses braces for lambda expressions (literals for anonymous functions).
{ true } is a lambda expression that represents a function that may or may not take arguments, but returns true every time.
So this code:
if (fileExtensions.isEmpty()) {
{ true }
} else {
{ fileExtensions.contains(it.extension) } // filter by extension
}
returns either:
{ true } - a function that takes a File as argument and always returns true, or
{ fileExtensions.contains(it.extension) } - a function that takes a File as argument and returns whether fileExtensions contains the extension of the File that it receives (it is the implicit name for the File argument)
Note: the fact that these functions take a File as argument is inferred by the compiler based on the return type of buildFileFilter().
if you CALL this one as a arguments in ".filter(...)", what would happed in the "(File)" syntax, is it automatically receive an arguments?
filter() itself actually expects a function as argument. The function you pass to filter() is called a predicate, because it takes one element of the list as argument and returns a Boolean that says whether this element should be included in the resulting list.
So if you apply filter to a List<File>, the predicate expected by filter is exactly of type (File) -> Boolean (it says whether we should put this File item in the resulting collection).
Calling buildFileFilter() returns a function as we have seen, and the function is perfectly of the right type to use it in filter. The File argument of the function returned by buildFileFilter() will be given by the filter function itself when it calls your filter function.

How do I specify an ActionListener in Kotlin?

I want to add an ActionListener to a JButton in Kotlin. In Java, I would just write this:
JPanel makeButtonPanel() {
JPanel panel = new JPanel(new FlowLayout());
JButton dirButton = new JButton("Change directory");
dirButton.addActionListener(e -> chooseDirectory());
panel.add(dirButton)
return panel;
}
But it's not so simple in Kotlin. I first tried this:
private fun makeButtonPanel() : JPanel {
val panel = JPanel(FlowLayout())
val dirButton = JButton("Choose")
dirButton.addActionListener(e -> chooseDirectory()) // error message here
// ...
}
private fun chooseDirectory() { ... }
But I'm getting this error message:
Type Mismatch
Required: ((ActionEvent!) -> Unit)!
Found: KFunction1<ActionEvent, Unit>
I understand that the ! means that this is a java method with uncertain nullability, but that doesn't help me understand how to write it. All I want it to do is call the chooseDirectory() method. There must be a clean, simple way to do this, but I don't see it.
As you've discovered, you need to use braces ({ }).
This is because braces are a necessary part of defining a lambda in Kotlin.  (That differs from languages like Java and Scala, where the necessary part is the -> or => arrow.  That's because in Kotlin the arrow is optional if there are one or no parameters; if one, the it keyword is used.)
Without the braces, the code would call your chooseDirectory() function, and try to pass its result to addActionListener() — which obviously wouldn't work.
Braces are also sufficient: they're taken as defining a lambda unless you're giving the body of a function or method or an if/when branch.  (Again, this differs from most C/Java-like languages.  In Kotlin, if you just want a block scope, you have to use a construct such as run.)
As for the parentheses, they're optional here.  You could include them if you wanted:
dirButton.addActionListener({ chooseDirectory() })
But Kotlin has a convention that if a function's last parameter is a function, you can pass it after the parens:
dirButton.addActionListener(){ chooseDirectory() }
And if that would make the parens empty, then you can omit them entirely:
dirButton.addActionListener{ chooseDirectory() }
That's to allow functions that look like new language syntax.  For example, you may have met the with function:
with(someObject) {
itsProperty = someValue
}
That's just a perfectly ordinary function, defined in the standard library, and taking a function as its last parameter.  Similarly, repeat:
repeat(10) {
// Some code to be run 10 times…
}
There's one further thing worth mentioning here.  In Kotlin, lambdas are one way to define functions, which are first-class types and can be defined, passed around, and used just like other types.  This differs from Java, which has traditionally used interfaces for those purposes — often interfaces with a Single Abstract Method (‘SAM interfaces’) — and in which lambdas are little more than syntactic sugar for defining an anonymous implementation of such an interface.
As a special case, for interoperability, Kotlin allows a lambda to define an implementation of a Java SAM interface (or, since Kotlin 1.4, of a Kotlin fun interface), instead of a function.
ActionListener is a Java SAM interface, which is why you can use a lambda here.
Okay, I figured it out, and it was pretty simple. I just have to dispense with the parentheses and say
dirButton.addActionListener { chooseDirectory() }
I'm still not clear on when I should use braces instead of parentheses.

Any significant differences between lambda expressions & anonymous function in Kotlin?

Kotlin has these 2 features and I think there're no significant differences between these two
regardless of :
syntax
// lambda
val toUpper = { value: String ->
if (value.isEmpty()) "empty value"
else value.toUpperCase()
}
// anonymous func
val toUpper = fun(value: String): String {
if (value.isEmpty()) return "empty value"
else return value.toUpperCase()
}
flexibility to use return statement on anonymous function
I'm still digesting these features and hope you guys can help me pass through it.
Thanks.
Two differences according to Kotlin Reference:
(I think the more significant one out of the two) An anonymous function is still a function, so returning from it behaves the same as returning from any function. Returning from a lambda, however, actually returns from the function enclosing the lambda.
The return type of a lambda is inferred, while you can explicitly specify a return type for an anonymous function.
This website states: "Lambdas Expressions are essentially anonymous functions that we can treat as values – we can, for example, pass them as arguments to methods, return them, or do any other thing we could do with a normal object." (link)
So the answer is no, there isn't a difference between the two, they are interchangeable. Both of the codes you show above, will in the end return the same value to that variable
Besides the differences pointed by #jingx, you can not local return from a lambda that is not inlined.
So, the next snippet will not compile unless you add inline to the extension() function, thus, instructing the compiler to copy the function's content whenever it is referenced:
fun doSomethingWithLambda(){
10.extension{
if(it == 10)
return//compiler error
}
println("hello")
}
fun Int.extension(f: (Int)->Unit){
f(this)
}

When do I use another function without paramters in Kotlin?

I'm a novice of Kotlin.
I found that I can use another function without parameters even if it has.
Let me know when I can use it.
Q1) Why can I use 2 types? (with parameters & without parameters) Is it Kotlin's feature?
Q2) What does it mean? ((Result!) -> Unit)!
It seems you are confused, you can never use a function without arguments. If the function has arguments then you have to fill the slot somehow.
The closest thing that could relate to what you are referring to is default values for arguments.
fun example(boolean: Boolean = true) {}
example()
example(true)
example(false)
You can omit the argument because it has defaulted in the function signature.
The documentation
What you are showing in the image file is a lambda.
In the first example:
signIn(listener: Session...)
That seems to be a callback. So it is gonna be an interface or maybe an abstract class called when some async operation is finished.
The second example, it is the callback implemented as a lambda
signIn() { result ->
//do something
}
In Kotlin the last argument if it is a lambda or something that can be implemented as a lambda can be moved out of the parenthesis for syntactic sugar. A lambda is like an anonymous function, it is a literal of a function.
By example you can declare a lambda:
val lambda = {text: String -> text.lenght % 2 == 0}
fun setRuleForText(rule: (String)-> Boolean) {...}
setRuleForText(lambda)
setRuleForText() { text: String
text.isNotEmpty()
}
In this case, the argument is a kotlin function. The argument rule is a function that receives a String as an argument and returns Boolean. Something to point out is that expressions return the last written value without the need for the reserved return word.
This is the documentation. And here you can see from a good source more about functions (the author is a Kotlin certified trained by Jetbrains)
In your case (Result) -> Unit means the lambda should receive a Result type as argument and then return Unit (unit is like void in Java but is more than that), no explicit return type.
signIn() { result ->
//do something
}
Most of the types, the argument on lambdas is inferred automatically, but if not, then
signIn() { result: Result ->
//do something
}
Both of the listed functions take a parameter.
The first is:
signIn(listener: Session.SignInListener!)
That takes a single parameter, of type Session.SignInListener.  (The ! means that Kotlin doesn't know whether it's nullable or not, because it's from Java and isn't annotated.)
The other is:
signIn {...} (listener: ((Result!) -> Unit)!)
That's the IDE's representation of the function with this signature:
signIn(listener: ((Result!) -> Unit)!)
That takes a single parameter, which is a function type (see below).
The reason the IDE shows it with braces is that in Kotlin, if the last parameter to a function is a lambda, you can move it outside the parentheses.  So a call like this:
signIn({ println(it) })
could equally well be written like this:
signIn() { println(it) }
The two forms mean exactly the same.  And, further, if the lambda is the only parameter, you can omit the parens entirely:
signIn { println(it) }
Again, it means exactly the same thing.
That syntax allows you to write functions that look like new language syntax.  For example:
repeat (10) {
// ...
}
looks like a new form of loop construct, but it's really just a function called repeat, which takes two parameter (an integer, and a lambda).
OK, let's look at that function type: ((Result!) -> Unit)!
That's the type of a function which takes one parameter of type Result, and returns Unit (i.e. nothing useful; think of it as the equivalent of void).  Again, it's complicated because Kotlin doesn't know about the nullability; both the Result parameter and the parameter holding this function have !s to indicate this.  (Without them, it would just be (Result) -> Unit.)

How can I pass property getter as a function type to another function

How can I pass property getter to a function that accepts function type?
Here is an example of what I want achieve:
class Test {
val test: String
get() = "lol"
fun testFun(func: ()->String) {
// invoke it here
}
fun callTest() {
testFun(test::get)
// error: Type mismatch: inferred type is
// KFunction1<#ParameterName Int, Char> but () -> String was expected
}
}
Is there a way?
You can reference the getter by writing ::test (or this::test).
When you write test::get, you are actually referencing the get method on String. That method takes an index and returns the character at that index.
If the property was a var and you want a reference to its setter, you can write ::test::set.
For more info on property references, see here: https://kotlinlang.org/docs/reference/reflection.html#bound-function-and-property-references-since-11
As already mentioned, you can use this::test to refer to the getter. Alternatively, if you have kotlin-reflect, you can do this::test.getter.
When you pass the field as a function, it assumes you mean the getter. As a result, if you want the setter, you have two options:
this::test::set
or
this::test.setter
The latter, just like this::test.getter requires kotlin-reflect, or the program will crash (tested locally with Kotlin 1.2.50)
You can, however, get the getter in another way. But I recommend you just stick with this::test because it's shorter.
You can do:
this::something::get
With just something::get it refers to the method inside the String class, which returns a char at an index. For reference, the method declaration:
public override fun get(index: Int): Char
If you don't mind, just use { test } (e.g. testFun { test }). This will exactly translate to your () -> String. The next best alternative is probably ::test (or this::test) as was already mentioned.
The second has probably only minor (negligible?) impact on performance. I did not test it myself, nor did I found any source which tells something regarding it. The reason why I say this, is how the byte code underneath looks like. Just due to this question I asked myself about the difference of the two: Is the property reference (::test) equivalent to a function accessing the property ({ test }) when passed as argument e.g. `() -> String`?
It seems that you are doing something wrong on logical level.
If you are overriding get method of a variable, then you can access it's value through this get method. Thus, why bother with test::get (which is totally different method, by the way, all you are doing is trying to access char from string), when you can just access variable by it's name?