Question
You have a Kotlin function that accepts another function as a parameter:
fun foo(m: String, bar: (String) -> Unit) {
bar(m)
}
You can call it with a lambda:
foo("a message", { println("this is a message: $it") })
// or using trailing lambda syntax
foo("a message") { println("this is a message: $it") }
Now suppose you also have this function:
fun buz(m: String) {
println("another message: $m")
}
Can you pass buz as the function argument to foo instead of writing a lambda inline?
For example, can something like this work?
foo("a message", buz)
Short Answer
By the end of this page, you will understand how Kotlin treats functions as values, how to pass a named function to another function, and when to use a lambda versus a function reference such as ::buz. You will also learn the function type rules that must match for this to work.
Concept
In Kotlin, functions are first-class values. That means you can:
- store them in variables
- pass them to other functions
- return them from functions
Your function foo expects a parameter named bar with this type:
(String) -> Unit
That type means:
- it takes one
Stringargument - it returns
Unit(no useful return value)
The function buz has this signature:
fun buz(m: String): Unit
This matches the same shape:
- one
Stringparameter - returns
Unit
So yes, buz can be passed to foo, but in Kotlin you usually pass a function reference, not just the bare function name.
Mental Model
Think of a function like a tool in a toolbox.
- A lambda is like creating a tool on the spot.
- A named function is like using a tool you already built and labeled.
- A function reference (
::buz) is like handing someone the labeled tool so they can use it later.
So foo is saying:
Give me a message and also give me a tool that knows what to do with a
String.
You can give it:
- a brand new tool:
foo("hello") { println(it) }
- or an existing tool by reference:
foo("hello", ::buz)
Syntax and Examples
Core syntax
A function type in Kotlin looks like this:
(String) -> Unit
A function that accepts another function:
fun foo(m: String, bar: (String) -> Unit) {
bar(m)
}
A named function with a matching signature:
fun buz(m: String) {
println("another message: $m")
}
Pass the named function using a function reference:
foo("a message", ::buz)
Lambda vs function reference
Using a lambda
foo("a message") { println("this is a message: $it") }
Using a named function
{
println()
}
foo(, ::buz)
Step by Step Execution
Consider this example:
fun foo(m: String, bar: (String) -> Unit) {
bar(m)
}
fun buz(m: String) {
println("another message: $m")
}
fun main() {
foo("a message", ::buz)
}
Here is what happens step by step:
main()callsfoo("a message", ::buz).- The first argument is the string
"a message". - The second argument is a reference to the function
buz. - Inside
foo, the parametermbecomes"a message". - Inside
foo, the parameterbarnow refers tobuz. fooexecutes .
Real World Use Cases
Higher-order functions and function references are common in real Kotlin code.
1. Processing collections
val names = listOf("ana", "bob", "carl")
println(names.map(String::uppercase))
Here String::uppercase is a function reference.
2. Validation rules
fun validate(input: String, rule: (String) -> Boolean): Boolean {
return rule(input)
}
You can pass different validation functions depending on context.
3. Logging or formatting callbacks
fun processMessage(message: String, logger: (String) -> Unit) {
logger(message)
}
This lets you swap out how messages are handled.
4. Event handling
UI frameworks and asynchronous code often expect functions to run later when something happens.
5. Reusable business rules
Real Codebase Usage
In real projects, developers use this concept to keep logic reusable and easy to test.
Common patterns
Guarded processing
fun withNonEmptyText(text: String, action: (String) -> Unit) {
if (text.isBlank()) return
action(text)
}
This uses an early return before calling the provided function.
Reusing named functions
fun logMessage(message: String) {
println("LOG: $message")
}
fun handle(message: String, callback: (String) -> Unit) {
callback(message)
}
handle("Started", ::logMessage)
This is clearer than repeating the same lambda in multiple places.
Passing behavior into utilities
fun transformAndPrint(value: String, transformer: () -> ) {
println(transformer(value))
}
Common Mistakes
1. Forgetting :: for a named function
This is the main issue in the original question.
Incorrect
foo("a message", buz)
Correct
foo("a message", ::buz)
Use :: when passing a named function as a value.
2. Function signature does not match
If foo expects (String) -> Unit, the function must accept one String and return Unit.
Broken example
fun wrongBuz(m: Int) {
println(m)
}
foo("a message", ::wrongBuz)
This fails because Int is not String.
3. Returning the wrong type
Broken example
Comparisons
| Approach | Example | Best use | Notes |
|---|---|---|---|
| Lambda | foo("x") { println(it) } | Short one-off behavior | Great for inline logic |
| Function reference | foo("x", ::buz) | Reusing an existing function | Cleaner when the function already exists |
| Anonymous function | foo("x", fun(m: String) { println(m) }) | Rare cases needing explicit syntax | More verbose |
Function call vs function reference
| Syntax | Meaning |
|---|---|
buz("hello") |
Cheat Sheet
// Function that accepts another function
fun foo(m: String, bar: (String) -> Unit) {
bar(m)
}
// Named function
fun buz(m: String) {
println(m)
}
// Pass lambda
foo("hello") { println(it) }
// Pass named function
foo("hello", ::buz)
Rules
- Use a function type like
(String) -> Unitto declare a function parameter. - Use
::functionNameto pass a named function. - The parameter types and return type must match.
buz("x")calls the function.::buzpasses a reference to the function.
Common matching examples
fun printText(s: String) { println(s) } // matches (String) -> Unit
fun length: = s.length
{ }
FAQ
Can I pass a named function as a parameter in Kotlin?
Yes. Use a function reference with ::, such as ::buz.
Why does foo("a message", buz) not work?
Because Kotlin needs a function reference when you want to pass the function itself as a value. Use foo("a message", ::buz).
What does (String) -> Unit mean in Kotlin?
It means a function that takes one String argument and returns Unit.
When should I use a lambda instead of a function reference?
Use a lambda for short one-time logic. Use a function reference when a suitable named function already exists.
Does the function signature need to match exactly?
Yes. The number of parameters, their types, and the return type must be compatible.
What is the difference between buz("x") and ::buz?
buz("x") executes the function immediately. ::buz creates a reference you can pass to another function.
Mini Project
Description
Build a small message processor that accepts a message and a handler function. This demonstrates how to pass different behaviors into the same function, including both lambdas and named functions. It mirrors real applications where the same input might be logged, formatted, validated, or saved differently.
Goal
Create a Kotlin program where one processing function can send a message to different handler functions.
Requirements
- Create a function that accepts a
Stringmessage and a handler of type(String) -> Unit. - Create at least two named handler functions with the same signature.
- Call the processor once with a function reference and once with a lambda.
- Print different outputs so the behavior change is visible.
Keep learning
Related questions
Android AlarmManager Example: Scheduling Tasks with AlarmManager
Learn how to use Android AlarmManager to schedule tasks, set alarms, and handle broadcasts with a simple beginner example.
Can You Extend a Data Class in Kotlin? Inheritance, Limits, and Better Alternatives
Learn why Kotlin data classes cannot be extended, what causes the component function clash, and which alternatives to use instead.
Difference Between List and Array in Kotlin
Learn the difference between List and Array in Kotlin, including mutability, size, APIs, performance, and when to use each one.