Why do Kotlin Lambda functions not execute when called? - kotlin

In the following code I have 2 functions - first one wrapped in a lambda body and the other without.
fun first() = { println("first")}
fun second() = println("second")
first()
second()
Only second() prints - why is this?

The first one is a function that returns a function. What happens in fact is that first() returns another function that prints "first", but doesn't execute it.
To do this you have to call it by adding another set of of parenthesis:
first()()
// Or
val resultOfFirst = first()
resultOfFirst()
This happens because the = sign for functions is analogous to a return statement and when you wrap things in {} you're in fact creating a lambda. Hence, first returns a lambda, but doesn't execute it

It's very simple. Check types of those:
fun first(): () -> Unit = { println("first") }
fun second(): Unit = println("second")
So, when you call first you get lamda expression. To invoke this function use .invoke() (or simply ()):
first().invoke()
// or
first()()
Second is obvious - it's executed on call.

The function first returns a function { println("first")}.
Calling first() does nothing - not even its return argument is catched.
Without a lambda an equivalent would be, maybe it is easier to understand it in this form:
fun firstWithoutLambda() = fun() { println("first w/o lambda")}
To call them:
first().invoke()
firstWithoutLambda().invoke()
which will print the messages that you would expect.
From the original Kotlin tutorial a good article: https://kotlinlang.org/docs/reference/lambdas.html

Try
first()()
or
first().invoke()
first returns a function, it does not invoke it.

Related

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

Is there a simple null safe operator for Kotlin function references?

I'd like to pass a function reference on a nullable object. To take an Android example, say I want to use Activity#onBackPressed from a fragment that is a child of that actvity.
If I wanted to invoke this function, I could easily do
activity?.onBackPressed()
However, say I wanted to pass that as a reference instead:
val onBackPressedRef = activity::onBackPressed
This gives the familiar null safe error of Only safe or non null assserted calls are allowed...
I can get the error to go away with the following, but using !! is obviously not ideal:
val onBackPressedRef = activity!!::onBackPressed
Attemping activity?::onBackPressed was my first instinct, but this also breaks with several errors, where the interpreter seems confused.
val onBackPressedRef = activity?.let { it::onBackPressed }
This last variation works, but it's a lot more ugly than just using ?::. I checked all the docs I could find, but I feel like I'm missing something. Any ideas?
You are right, there is no ?:: operator in Kotlin.
You have several alternatives:
1. let and run
Thus, you have to use a helper function. Instead of let(), you can also use run(), making the expression a tiny bit shorter:
val onBackPressedRef = activity?.let { it::onBackPressed }
val onBackPressedRef = activity?.run { ::onBackPressed }
But keep in mind that either way, the invocation will be more verbose, too:
onBackPressedRef?.invoke(args)
Thus you should ask yourself, if this is really what you want, or if a no-op function call is also acceptable.
2. Closures
You could use a closure -- this will change semantics however:
val onBackPressedRef = { activity?.onBackPressed() }
Here, onBackPressedRef is not nullable anymore, so you can call it using the () operator, and in case of null activity it will have no effect.
3. Helper function
If function references with nullable objects are something you encounter a lot, you can write your own little abstraction:
// Return type: () -> Unit
fun <T> funcRef(obj: T?, function: T.() -> Unit) = { obj?.function() }
This trades a different syntax for a non-null function variable:
// activity can be null
val onBackPressedRef = funcRef(activity, Activity::onBackPressed)
// Callable directly
onBackPressedRef()

Kotlin fun() vs lambda is there difference?

This question is about fun() vs a lambda block definitions and scopes.
i have tried define the expressions in two ways. Here is what i have tried:
val myFunction = fun(){
println("i am in a function")
}
//but i also tried doing this:
val myFunction = {
println("i am in a lambda")
}
my problem is i do not know if they are equivalent and same thing ?
The differences are best described in https://kotlinlang.org/docs/reference/lambdas.html#anonymous-functions:
Anonymous functions allow you to specify return type, lambdas don't.
If you don't, return type inference works like for normal functions, and not like for lambdas.
As #dyukha said, the meaning of return is different:
A return statement without a label always returns from the function declared with the fun keyword. This means that a return inside a lambda expression will return from the enclosing function, whereas a return inside an anonymous function will return from the anonymous function itself.
There is no implicit it parameter, or destructuring.
Your specific cases will be equivalent, yes.
See the reference: https://kotlinlang.org/docs/reference/lambdas.html
There are several ways to obtain an instance of a function type:
Using a code block within a function literal, in one of the forms:
a lambda expression: { a, b -> a + b },
an anonymous function: fun(s: String): Int { return s.toIntOrNull() ?: 0 }
Both give you a function object which can be used interchangeably

Kotlin anonymous function use case?

Based on my understanding, anonymous function in Kotlin allow you to specify return type. In addition to that, return statement inside anonymous will exit only the function block, while in lambda it will exit the enclosing function.
Still, I can't imagine what would be the real world use case of anonymous function in Kotlin that lambda syntax cannot provide?
Kotlin Higher Order Function and Lambda
The use case is that sometimes we may wish to be explicit about the return type. In those cases, we can use so called an anonymous function. Example:
fun(a: String, b: String): String = a + b
Or better return control like:
fun(): Int {
try {
// some code
return result
} catch (e: SomeException) {
// handler
return badResult
}
}
Anonymous functions (a.k.a function expressions) are very handy when you have to pass a huge lambda with complex logic and want early returns to work. For example if you write a dispatcher in spark-java:
get("/", fun(request, response) {
// Your web page here
// You can use `return` to interrupt the handler
})