Kotlin: how to pass a function as a parameter? Let's figure it out with examples
\n\nHi, friend! If you've ever written in Kotlin and wondered: "How do I pass a function as a parameter to another function?" — then you've come to the right place. This question on Stack Overflow has thousands of views, and that's no surprise. Functional programming in Kotlin is not just a trendy feature, but a powerful tool that makes code cleaner, shorter, and more expressive.
\n\nIn this article, we won't just give a dry answer. We'll break down everything from simple lambda expressions to advanced techniques. You'll learn how to use Function types, the function reference operator ::, and even how to avoid common beginner mistakes. Let's go!
Why is this important? Three reasons to use functions as parameters
\n\n- \n
- Flexibility: You can write one function that does different things depending on which function you pass into it. \n
- Readability: Code becomes declarative — you describe what to do, not how to do it. \n
- Reusability: Eliminate code duplication by extracting common patterns into higher-order functions. \n
Basics: Function Types
\n\nIn Kotlin, functions are first-class objects. This means they have their own type. A function type is described like this: (Parameters) -> ReturnType. For example:
// A function that takes an Int and returns a String\nval intToString: (Int) -> String = { number -> "Number: $number" }\n\n// A function that takes nothing and returns nothing\nval doNothing: () -> Unit = { println("Hello!") }\n\n// A function with two parameters\nval sum: (Int, Int) -> Int = { a, b -> a + b }\n\n\nNotice Unit — it's the equivalent of void in Java/JavaScript. If a function returns nothing, its type is () -> Unit.
How to pass a function as a parameter: first example
\n\nLet's say we're writing a function that performs some operation on a number twice. Instead of hardcoding the operation, we'll pass it as a parameter:
\n\nfun applyTwice(x: Int, operation: (Int) -> Int): Int {\n val firstResult = operation(x)\n return operation(firstResult)\n}\n\n// Usage:\nval result = applyTwice(5) { it * 2 } // Lambda\nprintln(result) // Output: 20 (5*2 = 10, 10*2 = 20)\n\n// Or with a named function:\nfun double(x: Int) = x * 2\nval result2 = applyTwice(5, ::double)\nprintln(result2) // Also 20\n\n\nSee how elegant that is? In the first case, we used a lambda expression (anonymous function), and in the second, a reference to an existing function via the :: operator. Both approaches are valid, and we'll cover them in more detail.
Ways to pass a function (detailed breakdown)
\n\n1. Lambda expressions (the most popular way)
\n\nA lambda is an anonymous function that can be passed directly. In Kotlin, lambdas have a concise syntax:
\n\nval list = listOf(1, 2, 3, 4, 5)\n\n// Passing a lambda to the filter function\nval evenNumbers = list.filter { it % 2 == 0 }\nprintln(evenNumbers) // [2, 4]\n\n// If there are multiple parameters:\nval numbersWithIndex = list.mapIndexed { index, value -> "$index: $value" }\nprintln(numbersWithIndex) // ["0: 1", "1: 2", ...]\n\n\nImportant: If the lambda is the last parameter of a function, it can be moved outside the parentheses. This makes the code look like built-in language constructs. This is exactly how filter, map, forEach, and others work.
Example with explicit parameter specification (when there is more than one parameter):
\n\nfun performAction(a: Int, b: Int, action: (Int, Int) -> String) {\n println(action(a, b))\n}\n\n// Call with lambda\nperformAction(3, 4) { x, y -> "Sum: ${x + y}" }\n<