Functions

The fun keyword define new function.

Kotlin functions can be declared at the top level in a file, meaning you do not need to create a class to hold a function like in Java.

Functions can also be written within other functions to encapsulate useful functionality within a nested function scope. Also functions can be declared as extension functions.

/* general syntax
fun <func-name>(<arg-name>:<arg-type>): <return-type>{

}
*/

fun sum(a: Int, b: Int) : Int {
    return a+b
}

passing arguments

A method can have a list of arguments in parentheses, separated by commas.

Argument may have default value. You can skip some arguments with default values. However, after the first skipped argument, you must name all subsequent arguments. Place arguments that don’t have default values at the beginning of a function’s arguments list.

fun reformat(
    str: String,
    normalizeCase: Boolean = true,
    upperCaseFirstLetter: Boolean = true,
    divideByCamelHumps: Boolean = false,
    wordSeparator: Char = ' ',
) { /*...*/ }

// use all arguments with default values
reformat("This is a long String!")

// normalizeCase and wordSeparator arguments with default values
reformat("This is a short String!", 
    upperCaseFirstLetter = false, 
    wordSeparator = '_')

variable-length argument list

The vararg modifier specifies the variable number of arguments.

Only one parameter can be marked as vararg. If a vararg parameter is not the last one in the list, values for the following parameters can be passed using the named argument syntax, or, if the parameter has a function type, by passing a lambda outside parentheses.

If you already have an array and want to pass its contents to the function, use the spread operator *.

fun <T> asList(vararg ts: T): List<T> {
    val result = ArrayList<T>()
    for (t in ts) // ts is an Array
        result.add(t)
    return result
}

val list1 = asList(1, 2, 3)

val a = arrayOf(1, 2, 3)
val list2 = asList(-1, 0, *a, 4)

return value

The return statement finishes function execution and return specified value if necessary to caller.

The Unit type is default return type of function.

Declaration of return type can be omitted for type Unit or when a function returns a single expression.

fun printHello(name: String?): Unit {
    if (name != null)
        println("Hello $name")
    else
        println("Hi there!")
    // `return Unit` or `return` is optional
}

// return type omitted
fun printHello(name: String?) { ... }

// function with single expression
fun double(x: Int): Int = x * 2

// return type omitted
fun double(x: Int) = x * 2

inline

The inline modifier allows to inline the function itself into the call site. This is useful when

  • the function has a lambda parameter, in which case its body will be inlined
  • a short function body, for example, calls another function or returns a simple boolean expression
// inline function
inline fun hypot3(x: Double, y: Double, z: Double): Double = 
      sqrt(x * x + y * y + z * z)

// inline extension function
inline fun Vector2.distanceTo(vec2: Vector2) = 
      hypot(vec2.x - x, vec2.y - y)

//----------------------------------------------
// lock is inline function with lambda paramter
lock(l) { foo() } 

// this call will generate following code
l.lock()
try {
    foo()
} finally {
    l.unlock()
}

overloading

Kotlin supports overloading. This means, you can have several functions with same name but with different number of arguments or types of arguments in the same scope.

recursion

The tailrec modifier says to the compiler to optimize the recursion to the efficient loop.

val eps = 1E-10 // "good enough", could be 10^-15

tailrec fun findFixPoint(x: Double = 1.0): Double =
    if (Math.abs(x - Math.cos(x)) < eps) x else findFixPoint(Math.cos(x))

// will be transformed to the

val eps = 1E-10 // "good enough", could be 10^-15

private fun findFixPoint(): Double {
    var x = 1.0
    while (true) {
        val y = Math.cos(x)
        if (Math.abs(x - y) < eps) return x
        x = Math.cos(x)
    }
}