Lambda Functions
Lambda Functions
Guruprasad Hegde
13 min read
Like other data types that you can express with literal values — such as an Int type of a 31 value and a String type of a
"Lambda" value—you can also declare function literals, which are called lambda expressions or lambdas for short. You
use lambda expressions extensively in Android development and more generally in Kotlin programming.
A lambda expression in Kotlin is enclosed in curly braces {}. Inside the braces, you declare parameters (with optional
type annotations), followed by an arrow ->, and then the code body. If the return type isn’t Unit, the last expression in the
body is automatically treated as the return value.
There are four main variations of function types, depending on whether they
take parameters and whether they return a value.
1. Function Type with Parameters and a Return Type
This type of function takes one or more parameters and returns a value.
Syntax:
Example:
Syntax:
Example:
val printSum: (Int, Int) -> Unit = { a, b -> println("Sum: ${a + b}") }
Syntax:
() -> ReturnType
Example:
• Parameters: None.
• Return Type: String (the function returns a greeting).
Syntax:
() -> Unit
Example:
val sayHello: () -> Unit = { println("Hello!") }
• Parameters: None.
• Return Type: Unit (the function only prints "Hello!").
Explanation: In this example, each element in the numbers list is referred to as it within the lambda, and it is multiplied
by 2.
• When passing a lambda as an argument, if the lambda has one parameter, it is used implicitly.
• Example:
Explanation: The lambda passed to performOperation takes a single Int parameter, which is referred to as it inside the
lambda. The lambda multiplies it by 3.
3. Using it in UI Configuration
button.setOnClickListener {
Toast.makeText(context, "Button clicked!", Toast.LENGTH_SHORT).show()
}
Explanation: The setOnClickListener function takes a lambda with a single View parameter. The it keyword implicitly
refers to the clicked button.
• Explicit Naming for Clarity: Even with a single parameter, you might choose to explicitly name the parameter
instead of using it if it improves readability or clarity.
1. Syntax
Regular Functions:
• Defined using the fun keyword, with a name, parameters, and a return type.
• Example
Lambda Functions:
2. Usage Context
Regular Functions:
• Typically used when you need to define a reusable block of code that has a clear purpose and needs to be invoked
from multiple places.
• Can be top-level, member functions (inside a class or object), or local (inside another function).
Lambda Functions:
• Often used when you need a quick, inline function, especially when passing a function as an argument to a higher-
order function.
• They are more concise and are usually used in situations where defining a regular function would be overkill.
3. Naming
Regular Functions:
Lambda Functions:
• Anonymous and usually defined in place. They can be assigned to a variable, but the variable name is not the
function’s name.
• Example
4. Return Type
Regular Functions:
Lambda Functions:
• The return type is inferred from the expression in the body of the lambda. You don’t explicitly declare the return
type.
• Example
5. Receiver Type
Regular Functions:
• In regular functions, the receiver (if any) is declared in the function’s signature.
• Example
Lambda Functions:
• Lambdas can have a receiver, making them extension-like functions, often used with Kotlin’s scope functions (let,
apply, run, etc.).
• Example
6. Return Behavior
Regular Functions:
• Can use the return keyword to exit the function and return a value.
• Example
Lambda Functions:
• The return keyword inside a lambda expression refers to returning from the enclosing function, not just the
lambda. To return from the lambda itself, you can use a labeled return or avoid using return (by just letting the
lambda's last expression be the result).
• Example
7. Performance
• Regular Functions:
Compiled to regular methods, which can sometimes be slightly more optimized by the compiler.
• Lambda Functions:
May involve some overhead, especially when used heavily or in performance-critical code, due to their inline nature and
anonymous class creation.
• Regular functions are best for reusable, named pieces of code that have a specific purpose.
• Lambda functions are great for concise, inline code blocks, especially when working with higher-order functions
and functional programming paradigms in Kotlin.
• Passing Behavior as a Parameter: Lambda functions are often used as arguments to higher-order functions,
allowing you to pass behavior (like transformations, filtering, or processing logic) as a parameter.
• Example: Sorting a list of objects by a specific attribute.
2. Collection operations
• Mapping, Filtering, Reducing: Lambdas are commonly used with Kotlin’s collection functions like map, filter,
reduce, forEach, etc., to perform operations on collections.
• Example: Filtering even numbers from a list
3. Scope Functions
• let, apply, run, with, also: Scope functions use lambdas to operate on objects within a specific scope, often used
to initialize objects, perform operations, or handle nullability.
• Example: Initializing and configuring an object
4. Event Handling
• Callbacks: Lambdas are useful for handling events, such as button clicks in Android development, where you pass
a lambda to handle the event.
• Example: Handling a button click in Android
button.setOnClickListener {
println("Button clicked!")
}
6. Asynchronous Programming
• Callbacks and Continuations: Lambdas are commonly used to handle asynchronous operations, such as making
network requests or processing data in the background.
• Example: Handling the result of an asynchronous operation
callback("Data fetched")
}
• Code Reusability: Lambdas help create reusable blocks of code that can be passed around and executed in
different contexts, often used with inline functions to reduce overhead.
• Example: Creating a reusable logging function
9. Extension Functions
• Adding Behavior to Existing Classes: You can use lambdas with receiver types to add new functionality to
existing classes, making the code more expressive and concise.
• Example: Adding a custom operation to a list
10. UI Development
• Adding Behavior to Existing Classes: You can use lambdas with receiver types to add new functionality to
existing classes, making the code more expressive and concise.
• Example: Adding a custom operation to a list
How lambda function return the last statement and how does it work
internally?
In Kotlin, lambda functions automatically return the value of their last expression, which simplifies their
syntax and usage. This behavior is a key feature of lambda expressions and is rooted in how Kotlin handles
expressions and returns in lambdas.
product: This is the last expression in the lambda, so its value (which is a * b) is returned
Internal Mechanism: How It Works
Internally, Kotlin compiles lambda expressions into instances of anonymous classes that implement functional interfaces
(like FunctionN, where N is the number of parameters). The return value of the lambda is determined by the value of the
last expression, which becomes the return value of the invoke method of this anonymous class.
• When a lambda is defined, Kotlin creates an anonymous class that implements the corresponding functional
interface.
• For example, the lambda { a: Int, b: Int -> a + b } is compiled to an anonymous class that implements the
Function2<Int, Int, Int> interface.
2. Invoke Method:
• This anonymous class has an invoke method that takes the lambda’s parameters as arguments.
• The body of the lambda is executed inside this invoke method.
• During the execution of the invoke method, the last expression in the lambda’s body is evaluated, and its result is
returned by the invoke method.
• Kotlin does this automatically, so you don’t have to explicitly specify a return statement
When you invoke add(3, 4), Kotlin calls the invoke method on this anonymous class, passing 3 and 4 as arguments. The
invokemethod executes a + b and returns the result.
Performance Consideration
Kotlin uses inlining for lambdas passed to higher-order functions marked with the inline keyword. When a
lambda is inlined, its code is directly inserted at the call site, avoiding the overhead of creating an
anonymous class.
For non-inlined lambdas, the anonymous class approach is used, which involves a small amount of overhead
due to object creation and method invocation.
In Kotlin, this would be like defining a lambda function that takes care of ordering your coffee.
• You tell your friend, “Whenever I say I want a coffee, just order a cappuccino with extra foam.”
• In Kotlin, this is like defining a lambda
orderCoffee()
• Maybe sometimes you want a different kind of coffee. So, you modify your instruction: “Whenever I say I want
coffee, just ask me what kind, and then order it.”
• In Kotlin, this is like a lambda with parameters
• Now, when you tell your friend, “Order my coffee,” you can specify what kind you want
orderCoffee("latte")
orderCoffee("espresso")
• Suppose you want to know the price of the coffee after your friend orders it. You could instruct them, “Order my
coffee, and then tell me the price.”
• In Kotlin, the lambda could return a value
Anonymous Function
Anonymous functions in Kotlin are similar to lambda expressions but provide additional flexibility, especially when it
comes to specifying return types and using return statements. While lambda expressions are generally more concise,
anonymous functions offer features that are useful in certain scenarios.
2. Return Types
• Unlike lambdas, you can explicitly specify the return type of an anonymous function. This is particularly useful
when the type cannot be inferred or when you want to make the return type clear.
• Example
3. Usage of return
• In an anonymous function, the return keyword behaves as it would in a regular function, returning from the
anonymous function itself rather than the enclosing function. This contrasts with lambdas, where return can be
non-local if used in an inline function.
• Example
4. No Implicit it
• Unlike lambdas, anonymous functions do not have an implicit it parameter for single-parameter functions. You
need to explicitly define the parameter name.
• Example
• Control Flow with return: If you need to return from the function explicitly, especially within loops or other
complex structures, anonymous functions are more appropriate.
• Explicit Return Type: When you need to clearly define or specify the return type of a function, an anonymous
function can be more readable.
• Multiple Lines of Code: For longer or more complex logic where a lambda might become hard to read, an
anonymous function can be clearer.
• Lambdas: More concise, better suited for short and simple functions, can use implicit it for single parameters, and
can have non-local returns in inline functions.
• Anonymous Functions: More flexible with control over return types and explicit return, no implicit it, and better
for more complex logic.
Happy coding !!