Functions in Kotlin

Here, we are going to discuss functions in Kotlin Language. Kotlin functions are nearly identical to Java methods, though they behave more like JavaScript functions, because functions in Kotlin are more than just a named collection of statements. Functions are first-class citizens in Kotlin; you can use one wherever you would use a variable.

What we’ll talk about:

  • Declaring functions
  • Default parameters
  • Named parameters
  • Extension functions
  • Infix operators
  • Infix functions

Declaring Functions

Places where functions can be defined

  1. within a class, like methods in java (member functions)
  2. outside a class – they are called top-level functions
  3. inside other functions – they are called local functions.

Syntax to declare a function

fun functionName([parameters]) [:type]
{
      statements
}

Here, fun keyword is used to declare a function, it is followed by an identifier, that is the function name. We can also specify the type of data that function will return, though it is optional because Koltlin can infer the function’s return type by observing the function’s body declaration.

Following shows a basic declaration of a function that takes Int and String parameters.

fun displayMsg(n: Int, msg: String)
{
    var i = 1
    while(i <= n )
    {
        println(msg)
        i++        
    }
}
fun main()
{
    displayMsg(5,"hi")
}

Default arguments

// www.raviroza.com
// 23-Jan-22, 1.00 pm

fun DefaultArguDemo(n: Int, msg: String="hi")
{
    var i = 1
    while(i <= n )
    {
        println(msg)
        i++
    }
}
fun main()
{
    DefaultArguDemo(4)
    DefaultArguDemo(4,"hello")
}

In the above example, function DefaultArguDemo() is created with two parameters, 1st is integer and 2nd is string declared as default parameter with values. While calling this function we can skip the 2nd argument because it has been set with a default value of “hi”, though we can pass the 2nd parameter values if it is required as shown in example.

Named Parameters

We run into a problem while working with the default arguments. If we jumble the arguments, a compilation error will occur, so we must pass the actual arguments to the formal arguments in the same order as defined during function declaration.

Though, we can change the sequence of arguments passed to a function by using named parameters. Observe the following is the example


// www.raviroza.com
// 23-Jan-22, 1.00 pm

fun NamedParaDemo(name:String = "ravi r oza", city:String = "jamnagar", id:Int = 101)
{
    println("ID    : $id")
    println("Name  : $name")
    println("City  : $city")
}
fun main()
{
    NamedParaDemo(name="raviroza.com",id=201)
    NamedParaDemo(id=301,name="Oza Ravi")
}

In the above example, NamedParaDemo() function is declared with three default parameters. While calling the NamedParaDemo() function, we can change the sequence of parameters (jumble) by providing each parameter name.

It gives the advantage of passing function arguments in whatever order we want and to use default values for those parameters whose values are not passed while calling.

Variable arguments (var arg) function

// www.raviroza.com
// 24-Jan-22, 7.49 am

// var args function to accept any data type (int, char, string, float etc.,)
fun varArgsDemo(vararg v : Any)
{
    for(f in v)
    {
        print("$f ")
    }
    println()
}
// var args function to accept only float values
fun varArgsDemo1(vararg v : Float)
{
    for(f in v)
    {
        print("$f ")
    }
    println()
}

fun main() {
    
    varArgsDemo("ravi","oza","jamnagar")
    varArgsDemo(1,5,7,9,10,77)
     
    varArgsDemo1(10.45f,50.12f)
}

Above is an example of a variable argument parameter to a function. varArgsDemo () is a function that accepts varargs arguments of type Any, such a function can variable arguments, it is required when it is not certain how many arguments will be passed to a given function at run time.

Though, data type of varargs can be of any other data type, but to in above case, it is specified as so that it can any data type such as char, string, int, float etc.,

Single Expression Functions

A function that contains only one statement is known as Single Expression Function

fun sum(i: Int, i1: Int): Int {

    return i+i1
}

// above function can also be written as expression function as it
// contains only one statement

fun sumInt(a: Int, b: Int) = a + b
// compiler can infer the type that’s returned from the value of expression. 
//or
//fun sumInt (a: Int, b: Int): Int = a + b
// above is defined with explicit return type

fun main()
{
    //var c = sum(10,20)
    var c = sumInt(10,20)
    println("Sum = "+c)
}

Extension functions

Without having to inherit from the class or employ design patterns like Decorator, Kotlin allows you to extend a class with new features. This is accomplished through the use of extensions, which are special declarations.

To add an extension function to an existing class, define a new function appended to existing class as shown here in example: 

// www.raviroza.ccom
// 23-Jan-22, 1.00 pm

class ExtensionTest
{
    fun method1()
    {
        println ("Regular method inside of class ")
        println ("Regular ExtensionTest.method1() called")
        println()
    }
}
fun main()
{
    fun ExtensionTest.method2()
    {
        println ("Extension method added from outside of class ")
        println ("ExtensionTest.method2() called")
        println()
    }
    var ex = ExtensionTest();
    ex.method1()
    ex.method2()
}

In above example method1() of class ExtensionTest is declared inside the class whereas the method2() is created outside of ExtensionTest class.

Infix operators

Let’s look at two commonly used infix functions before we learn how to write a function in infix notation. When we use the || and && operations, the compiler looks up or and and functions respectively, and calls them.

// www.raviroza.ccom
// 23-Jan-22, 4.40 pm

fun main()
{
    val r = true
    val o = false

    var result: Boolean

    result = r or o // a.or(b)
    println("Result = $result")

    result = r and o // a.and(b)
    println("Result = $result")
}

In the the above program, a or b instead of a.or(b), and a and b instead of a.and(b) is used. It was possible because these two functions support infix notation.

Infix function

Infix function must satisfy the following requirements

  • is a member function or an extension function.
  • it must accept a single parameter.
  • it is marked with an infix keyword.
// www.raviroza.ccom
// 23-Jan-22, 4.57 pm

class MyMath
{
    // user defined infix member function
    infix fun factorial(num : Int): Int
    {
        var t = 1
        var n = num
        while(n>=1)
        {
            t = t * n
            n--
        }
        return t
    }
    infix fun evenOdd(num: Int)
    {
        if(num % 2 == 0)
            println ("$num is EVEN")

        else
            println ("$num is ODD")
    }
}
fun main()
{
    var m = MyMath()
    var x = 5
    var f = m factorial x

    println("Factorial of $x is $f")
    
    
    // various way to call infix method
    m.evenOdd(5)

    m evenOdd (7)

    m evenOdd 9

}

output

Factorial of 5 is 120
5 is ODD
7 is ODD
9 is ODD