What you'll learn
This module ties functional Kotlin together. You'll formalise function types, understand the inline keyword that makes higher-order functions fast, meet reified type parameters, and use function references cleanly.
By the end you'll be able to:
- Read and use function types
- Understand what
inlinedoes and why it matters - Use reified type parameters
- Use function, property, and constructor references
Function types
A function type describes a function's shape: its parameter types and return type, joined by an arrow. (Int, Int) -> Int means "takes two Ints, returns an Int." You can store functions in variables of these types, and pass or return them:
(Int, Int) -> IntParameter types
The types the function accepts, in parentheses.
Return type
After the arrow — what it produces.
// a variable holding a function, typed as (Int, Int) -> Int
val operation: (Int, Int) -> Int = { a, b -> a + b }
println(operation(3, 4)) // 7
// a function that RETURNS a function
fun operator(symbol: String): (Int, Int) -> Int = when (symbol) {
"*" -> { a, b -> a * b }
else -> { a, b -> a + b }
}
val multiply = operator("*")
println(multiply(3, 4)) // 12inline functions
Passing lambdas around normally creates small objects at runtime, which has a tiny cost. The inline keyword tells the compiler to copy the lambda's code directly into the call site instead — eliminating that overhead. This is why Kotlin's collection operations (all those map/filter calls) are as fast as hand-written loops:
// 'inline' copies the lambda's code into the call site — no lambda
// object is created. This makes higher-order functions as fast as a
// hand-written loop, which is why the stdlib functions are inline.
inline fun runTwice(action: () -> Unit) {
action()
action()
}
runTwice {
println("Running!")
}Note
inline for small higher-order functions where the lambda overhead matters. For everyday code you rarely write it yourself — but understanding it explains why Kotlin's functional style carries no performance penalty. (noinline and crossinline fine-tune the behaviour.)reified type parameters
Normally, generic type information is erased at runtime (Module 22), so you can't write value is T. But inside an inline function, a reified type parameter keeps the type — letting you check and use it at runtime. It's a small superpower:
// 'reified' lets you use the type T at runtime — only in inline functions
inline fun <reified T> firstOfType(items: List<Any>): T? =
items.firstOrNull { it is T } as? T
val mixed = listOf(1, "hello", 2.0, "world")
println(firstOfType<String>(mixed)) // hello
println(firstOfType<Int>(mixed)) // 1Function, property & constructor references
When a lambda would just call one existing function, a reference with :: says the same thing more concisely. There are three flavours: function (::triple), property (String::length), and constructor (::Person):
fun triple(n: Int) = n * 3
val nums = listOf(1, 2, 3)
println(nums.map(::triple)) // [3, 6, 9] — function reference
println(nums.map { triple(it) }) // [3, 6, 9] — equivalent lambdaRecap & quick check
Key takeaways
- A function type like (Int, Int) -> Int describes parameter types and a return type.
- inline copies a lambda's code into the call site, removing overhead — why Kotlin's functional style is fast.
- reified type parameters (only in inline functions) keep the type at runtime, enabling value is T.
- References with :: point to a function (::name), property (Type::prop), or constructor (::Type).
- You rarely write inline yourself, but it's why higher-order functions carry no performance penalty.
Quick check
1. What does the function type (String) -> Int mean?
2. What does the 'inline' keyword do?
3. Where can you use a 'reified' type parameter?
4. What does ::triple represent?
5. Why are Kotlin's map/filter operations fast despite using lambdas?
Excellent — you've completed Phase 2! You command lambdas, collection pipelines, scope functions, and extensions — the tools that make Kotlin so expressive. Next comes Phase 3 — Object-Oriented Kotlin.