Functions
To declare a function in Kotlin:
Use the
funkeyword.Specify the parameters in parentheses
().Include the return type if needed.
For example:
Function usage
Functions are called using the standard approach:
To call a member or extension function, use a period .:
Parameters
Declare function parameters using Pascal notation: name: Type. You must separate parameters using commas and give each parameter a type explicitly:
Inside the body of a function, received arguments are read-only (implicitly declared as val):
You can use a trailing comma when declaring function parameters:
Trailing commas help with refactorings and code maintenance: you can move parameters within the declaration without worrying about which is going to be the last one.
Parameters with default values
You can make a function parameter optional by specifying a default value for it. Kotlin uses the default value when you call the function without providing an argument that corresponds to that parameter. Parameters with default values are also known as optional parameters.
Optional parameters reduce the need for multiple overloads, since you don't have to declare different versions of a function just to allow skipping a parameter with a reasonable default.
Set a default value by appending = to the parameter declaration:
When you declare a parameter with a default value before a parameter without a default value, you can only use the default value by naming the argument:
Trailing lambdas are an exception to this rule, since the last parameter must correspond to the passed function:
Overriding methods always use the base method's default parameter values. When you override a method that has default parameter values, you must omit the default parameter values from the signature:
Non-constant expressions as default values
You can assign a parameter a default value that isn't constant. For example, the default can be the result of a function call or a calculation that uses the values of other arguments, like the len parameter in this example:
Parameters that refer to the values of other parameters must be declared later in the order. In this example, len must be declared after b.
In general, you can assign any expression as the default value of a parameter. However, default values are only evaluated when the function is called without the corresponding parameter and a default value needs to be assigned. For example, this function prints out a line only when it is called without the print parameter:
If the last parameter in a function declaration has a functional type, you can pass the corresponding lambda argument either as a named argument or outside the parentheses:
Named arguments
You can name one or more of a function's arguments when calling it. This can be helpful when a function call has many arguments. In such cases, it's difficult to associate a value with an argument, especially if it's null or a boolean value.
When you use named arguments in a function call, you can list them in any order.
Consider the reformat() function, which has 4 arguments with default values:
When calling this function, you can name some of the arguments:
You can skip all the arguments with default values:
You can also skip some arguments with default values, rather than omitting them all. However, after the first skipped argument, you must name all subsequent arguments:
You can pass a variable number of arguments (vararg) by naming the corresponding argument. In this example, it's an array:
Return types
When you declare a function with a block body (by putting instructions within curly braces {}), you must always specify a return type explicitly. The only exception is when they return Unit, in which case specifying the return type is optional.
Kotlin doesn't infer return types for functions with block bodies. Their control flow can be complex, which makes the return type unclear to the reader and sometimes even to the compiler. However, Kotlin can infer the return type for single-expression functions if you don't specify it.
Single-expression functions
When the function body consists of a single expression, you can omit the curly braces and specify the body after an = symbol:
Most of the time you don't have to explicitly declare the return type:
The compiler can sometimes run into problems when inferring return types from single expressions. In such cases, you should add the return type explicitly. For example, functions that are recursive or mutually recursive (calling each other) and functions with typeless expressions like fun empty() = null always require a return type.
When you do use an inferred return type, make sure to check the actual result because the compiler may infer a type that is less useful to you. In the example above, if you want the double() function to return Number instead of Int, you have to declare this explicitly.
Unit-returning functions
If a function has a block body (instructions within curly braces {}) and does not return a useful value, the compiler assumes its return type is Unit. Unit is a type that has only one value, also called Unit.
You don't have to specify Unit as a return type, except for functional type parameters. You never have to return Unit explicitly.
For example, you can declare a printHello() function without returning Unit:
Which is equivalent to this verbose declaration:
You can use a return statement inside an expression body if the function's return type is specified explicitly:
Variable number of arguments (varargs)
To pass a variable number of arguments to a function, you can mark one of its parameters (usually the last one) with the vararg modifier. Inside a function, you can use a vararg-parameter of type T as an array of T:
Then you can pass a variable number of arguments to the function:
Only one parameter can be marked as vararg. If you declare a vararg parameter anywhere other than last in the parameter list, you must pass values for the following parameters using named arguments. If a parameter has a function type, you can also pass its value by placing a lambda outside the parentheses.
When you call a vararg-function, you can pass arguments individually, as in the example of asList(1, 2, 3). If you already have an array and want to pass its contents to a function as a vararg parameter or as a part of it, use the spread operator by prefixing the array name with *:
If you want to pass a primitive type array as vararg, you need to convert it to a regular (typed) array using the .toTypedArray() function:
Infix notation
You can declare functions that can be called without parentheses or the period by using the infix keyword. This can help make simple function calls in your code easier to read.
Infix functions must meet the following requirements:
They must be member functions of a class or extension functions.
They must have a single parameter.
The parameter must not accept a variable number of arguments (
vararg) and must have no default value.
Note that infix functions always require both the receiver and the parameter to be specified. When you call a method on the current receiver using the infix notation, use this explicitly. This ensures unambiguous parsing.
Function scope
You can declare Kotlin functions at the top level in a file, meaning you do not need to create a class to hold a function. Functions can also be declared locally as member functions or extension functions.
Local functions
Kotlin supports local functions, which are functions declared inside other functions. For example, the following code implements the Depth-first search algorithm for a given graph. The local dfs() function inside the outer dfs() function to hide the implementation and handle recursive calls:
A local function can access local variables of outer functions (the closure). In the case above, the visited function parameter can be a local variable:
Member functions
A member function is a function that is defined inside a class or object:
To call member functions, write the instance or object name, then add a . and write the function name:
For more information on classes and overriding members see Classes and Inheritance.
Generic functions
You can specify generic parameters for a function by using angle brackets <> before the function name:
For more information on generic functions, see Generics.
Tail recursive functions
Kotlin supports a style of functional programming known as tail recursion. For some algorithms that would normally use loops, you can use a recursive function instead without the risk of stack overflow. When a function is marked with the tailrec modifier and meets the required formal conditions, the compiler optimizes out the recursion, leaving behind a fast and efficient loop based version instead:
This code calculates the fixed point of cosine (a mathematical constant). The function calls cos() repeatedly starting at 1.0 until the result no longer changes, yielding a result of 0.7390851332151611 for the specified eps precision. The code is equivalent to this more traditional style:
You can apply the tailrec modifier to a function only when it calls itself as its final operation. You cannot use tail recursion when there is more code after the recursive call, within try/catch/finally blocks, or when the function is open.
See also: