- Define a function with parameters and a return type
- Use default values, named arguments and single-expression functions
- Add extension functions to existing types
- Write a lambda and pass it to a higher-order function
Imagine you build the same greeting text in ten places in your program. When the text has to change, you will need to fix ten places! A function lets you write the code once, give it a name and call it as often as you like. You have already worked with functions: main, println and repeat are functions. Now you will create your own.
Declaring a function
A function starts with the word fun, followed by its name and its parameters in parentheses. In Kotlin every parameter must have a type: name: String. After the parentheses, a colon introduces the return type, and the result is given back with return. A function that returns nothing has the type Unit, and you can leave it out.
fun greet(name: String, greeting: String = "Hello"): String {
return "$greeting, $name!"
}
fun printLine(length: Int = 10) {
println("-".repeat(length))
}
fun main() {
println(greet("Aysel"))
println(greet("Murad", "Salam"))
println(greet(greeting = "Hi", name = "Leyla"))
printLine()
printLine(5)
}Hello, Aysel! Salam, Murad! Hi, Leyla! ---------- -----
greeting: String = "Hello"is a default value: if no argument is given in the call,"Hello"is used.greet(greeting = "Hi", name = "Leyla")uses named arguments: when you write the parameter names, the order does not matter and the code reads more clearly.printLinereturns nothing — its type isUnit; it just prints to the screen.
Single-expression functions
If the whole job of a function is to calculate one expression, you can drop the curly braces and return and write the expression after an = sign. The compiler infers the return type by itself. Since if and when are expressions, they can be used in such a function too.
fun square(x: Int) = x * x
fun isEven(n: Int) = n % 2 == 0
fun rectangleArea(width: Double, height: Double) = width * height
fun result(score: Int) = if (score >= 50) "passed" else "failed"
fun main() {
println(square(7))
println(isEven(10))
println(rectangleArea(4.0, 2.5))
println(result(73))
}49 true 10.0 passed
Extension functions
In Kotlin you can “add” a new function to an existing type, even to a standard type such as String or Int. To do this, write the type and a dot before the function name: fun String.shout(). Inside the function, this is the value itself. Such a function is then called like an ordinary method: "salam".shout().
fun String.shout() = uppercase() + "!"
fun Int.isEven() = this % 2 == 0
fun Double.toManat() = "$this AZN"
fun main() {
println("salam".shout())
println(8.isEven())
println(12.5.toManat())
}SALAM! true 12.5 AZN
Lambdas
A lambda is a short function without a name, written in curly braces: { x: Int -> x * 2 }. The parameters are to the left of the arrow and the body is to the right; the value of the last expression is the lambda's result. You can store a lambda in a variable, and its type is written like this: (Int) -> Int — “takes an Int, returns an Int”. If a lambda has only one parameter, you can leave it out and use the name it in the body.
fun main() {
val double = { x: Int -> x * 2 }
val add: (Int, Int) -> Int = { a, b -> a + b }
val greet: (String) -> String = { "Hello, $it!" }
println(double(21))
println(add(3, 4))
println(greet("Elvin"))
}42 7 Hello, Elvin!
Higher-order functions
A function that takes another function as a parameter (or returns one) is called a higher-order function. Below, applyTwice applies the operation it receives twice. If a lambda is the last argument, it can be written outside the parentheses. An existing function can be passed with ::, as in ::multiply.
fun applyTwice(x: Int, f: (Int) -> Int): Int = f(f(x))
fun calculate(a: Int, b: Int, operation: (Int, Int) -> Int): Int {
return operation(a, b)
}
fun multiply(a: Int, b: Int) = a * b
fun main() {
println(applyTwice(3) { it + 10 })
println(applyTwice(5) { it * it })
println(calculate(8, 2) { a, b -> a - b })
println(calculate(8, 2, ::multiply))
}23 625 6 16
applyTwice(5) { it * it }: first 5 · 5 = 25, then 25 · 25 = 625.The standard library is full of functions that take lambdas. Even repeat(3) { ... } from the previous lesson is a higher-order function! On strings, count counts the characters that match a condition, and filter keeps only those characters:
fun main() {
val word = "Programming"
println(word.count { it == 'm' })
println(word.filter { it !in "aeiou" })
println(word.any { it.isDigit() })
repeat(2) { i -> println("Attempt ${i + 1}") }
}2 Prgrmmng false Attempt 1 Attempt 2
repeat passes the step number, starting from 0, to the lambda.Key points
- A function is written as
fun name(param: Type): ReturnType { ... }; a function that returns nothing has the typeUnit. - Default values make arguments optional, and named arguments remove the dependence on order.
- Single-expression function:
fun square(x: Int) = x * x. - An extension function adds a new method to an existing type:
fun String.shout(). - A lambda is an unnamed function:
{ a, b -> a + b }; a single parameter is calledit. - A higher-order function takes another function as a parameter; a trailing lambda can go outside the parentheses.
Check yourself
10 questions. Every correct answer earns XP.
fun area(w: Int, h: Int = 2) = w * h, what is area(5)?