Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Kotlin have two syntaxes for lambdas / anonymous functions?

Tags:

Kotlin has two ways of declaring an anonymous function (aka a lambda). The two different syntaxes are:

val lambda =  { input : String -> 
  "received ${input}"
}

and

val anonymousFunction =  fun (input : String): String {
  return "received ${input}"
}

I understand the difference between the two (as outlined in this answer), but what I don't understand is why the language has two different ways of declaring the same thing.

Are there optimizations at work under the hood for one verses the other? Was the anonymous function version thought to be too verbose? Could the lambda version of the syntax not support a return type?

like image 969
gypsydave5 Avatar asked Jan 05 '18 10:01

gypsydave5


People also ask

What is an anonymous function in Kotlin?

The anonymous function syntax allows you to specify the receiver type of a function literal directly. This can be useful if you need to declare a variable of a function type with receiver, and then to use it later.

How does lambda function work in Kotlin?

Lambda expression is a simplified representation of a function. It can be passed as a parameter, stored in a variable or even returned as a value. Note: If you are new to Android app development or just getting started, you should get a head start from Kotlin for Android: An Introduction.

How do you write an anonymous function on Kotlin?

In Kotlin, we can have functions as expressions by creating lambdas. Lambdas are function literals that is, they are not declared as they are expressions and can be passed as parameters. However, we cannot declare return types in lambdas.

Are lambdas and anonymous functions the same?

In Python, an anonymous function is a function that is defined without a name. While normal functions are defined using the def keyword in Python, anonymous functions are defined using the lambda keyword. Hence, anonymous functions are also called lambda functions.


1 Answers

The key reason is the support for returns from lambdas. The rule for returns is that the return keyword returns from the nearest function declared with the fun keyword. In some scenarios, you want a return in a block of code to return from the enclosing function, so you use a lambda:

fun processElements(list: List<Element>): Boolean {      list.forEach { element ->           if (!element.process()) return false   // returns from processElements()      }      return true } 

In other scenarios, you want to return from the block but not from the enclosing function. When using a lambda, returning from the block requires the return@label syntax, which is somewhat clunky:

fun processElements(list: List<Element>) {      list.forEach { element ->           if (!needToProcessElement(element)) return@forEach // returns from block           element.process()      } } 

To avoid the clunkiness, we've provided an alternative syntax - anonymous functions - which allows you to use return directly to return from the block:

fun processElements(list: List<Element>) {     list.forEach(fun(element) {          if (!needToProcessElement(element)) return // returns from block         element.process()     }) } 

A secondary reason is that it's indeed impossible to fit the return type declaration into the syntax of a lambda, but this is very rarely needed in practice, so it's not particularly important.

like image 56
yole Avatar answered Sep 20 '22 00:09

yole