Kotlin with Copilot: Create a lambda function to add 2 numbers
Video: Kotlin with Copilot: Create a lambda function to add 2 numbers by Taught by Celeste AI - AI Coding Coach
Kotlin: Lambda to Add Two Numbers
val add: (Int, Int) -> Int = { a, b -> a + b }. The two-arg version of the doubler. The smallest possible "operation" lambda.
A small puzzle: store an addition operation as a lambda. Combines episode 25 (higher-order functions) and 29 (one-line lambdas).
The Copilot prompt
fun main() {
// Lambda to add two integers
val add: (Int, Int) -> Int =
Copilot generates:
val add: (Int, Int) -> Int = { a, b -> a + b }
val result = add(5, 7)
println("Sum: $result") // 12
Walkthrough
(Int, Int) -> Int — takes two Ints, returns Int. The lambda body a + b is the entire computation. No explicit return; single-expression body.
Calling: add(5, 7) returns 12.
Versus a regular function
fun add(a: Int, b: Int): Int = a + b
Same logic, different shape. The named function:
- Can be called from anywhere (after declaration).
- Cleaner stack traces ("called add(5, 7)" vs "called
(5, 7)"). - Slightly faster (JVM can inline named functions more aggressively, depending on context).
The lambda:
- Can be passed around, stored, returned.
- Captures local variables (closure).
- Used as a parameter to higher-order functions.
For a fixed operation, name the function. For a slot you'll fill in later, use a lambda.
Operator references
For the common operators, you don't even need a lambda:
val nums = listOf(1, 2, 3, 4, 5)
val sum = nums.reduce { a, b -> a + b } // 15
val sum2 = nums.reduce(Int::plus) // 15 — operator reference
Int::plus is the function reference for the + operator. Same effect as { a, b -> a + b }. Idiomatic when the lambda is just an operator.
Defining your own operator
For custom types, define operator overloads:
data class Money(val cents: Int) {
operator fun plus(other: Money) = Money(cents + other.cents)
operator fun minus(other: Money) = Money(cents - other.cents)
}
val a = Money(100)
val b = Money(50)
println(a + b) // Money(cents=150)
operator fun plus(other: T) makes a + b desugar to a.plus(b). Same for minus, times, div, rem, compareTo, equals, etc.
Now Money::plus is a function reference too:
val total = listOf(Money(100), Money(50), Money(25)).reduce(Money::plus)
Storing operations in a map
val ops: Map<String, (Int, Int) -> Int> = mapOf(
"+" to { a, b -> a + b },
"-" to { a, b -> a - b },
"*" to { a, b -> a * b },
"/" to { a, b -> a / b },
"%" to { a, b -> a % b },
)
fun calc(op: String, a: Int, b: Int): Int? = ops[op]?.invoke(a, b)
println(calc("+", 5, 3)) // 8
println(calc("*", 4, 6)) // 24
A simple calculator. The map dispatches by operator name. Adding "**" (power) is one new entry — no when-block to maintain.
Lambdas with side effects
val log: (Int, Int) -> Int = { a, b ->
println("Computing $a + $b")
a + b
}
val result = log(5, 7)
// Prints: "Computing 5 + 7"
// result = 12
Multiple statements in a lambda — the last expression is the return value. The println runs; the a + b is returned.
This is the simplest form of "decorator" — wrap a function with logging.
Currying (manually)
Kotlin doesn't have built-in currying, but you can simulate it with closures:
val add: (Int) -> (Int) -> Int = { a -> { b -> a + b } }
val add5 = add(5) // (Int) -> Int — partially applied
println(add5(3)) // 8
println(add5(10)) // 15
add(5) returns a function that adds 5 to its argument. The captured a = 5 lives as long as the returned function does.
Useful for partial application — fix some arguments early, take the rest later.
Variadic addition
For "add an arbitrary number of integers":
fun addAll(vararg nums: Int): Int = nums.sum()
println(addAll(1, 2, 3, 4, 5)) // 15
vararg parameters become an IntArray. .sum() is the built-in.
For lambdas, no vararg — they're fixed-arity:
val addAllLambda: (IntArray) -> Int = { it.sum() }
println(addAllLambda(intArrayOf(1, 2, 3, 4, 5))) // 15
Pass an array explicitly.
Common mistakes
Wrong number of params in the call. add(5) errors when add: (Int, Int) -> Int. Match the arity.
Using it for a 2-arg lambda. { it + it } is wrong (no implicit it for multi-arg). Use names: { a, b -> a + b }.
Forgetting type annotation when needed. val add = { a, b -> a + b } doesn't compile — Kotlin can't infer a's and b's types. Add either variable type or parameter types.
Returning Unit by accident. val add: (Int, Int) -> Int = { a, b -> println(a + b) } returns Unit (println's return). Last expression must produce the right type.
Treating + as something special. + between ints is just Int.plus(Int). Same machinery as any operator.
What's next
Episode 31: Lambda to square a number. Single-arg variant — same shape, simpler body.
Recap
val add: (Int, Int) -> Int = { a, b -> a + b }. Single-expression body, no return. Operator references like Int::plus work where the lambda is just an operator. Custom types can operator fun plus(...) to participate. Multi-statement lambdas: last expression is the return. Currying via closures: (Int) -> (Int) -> Int. For variadic, use a regular function with vararg.
Next episode: square lambda.