Kotlin. Named arguments of functions. The Nothing type

Named arguments of functions. The Nothing type. Overloading functions


Contents


Search other resources:

1. Concept of named arguments of functions

When calling a function, the usual passing of arguments to it can be replaced by using a different syntax. This syntax supports so-called named arguments of functions. In this case, the name of each function parameter is specified explicitly using the following syntax:

fun FuncName(param1 = value1, param2 = value2, ..., paramN = valueN)

here

  • param1, param2, paramN – the names of the parameters that are used when declaring the function;
  • value1, value2, valueN – the value of the arguments passed to the function.

Accordingly, the parameter named param1 receives the value of the argument value1, the parameter named param2 receives the value of the argument value2, and so on.

Since when using named arguments, each parameter receives its value by name, it is allowed to change the order of the parameter names.

For example, if a function is declared so that it receives 3 parameters named a, b, c, which are of types Int, Char, Double, respectively

// A function that receives 3 parameters of types Int, Char, Double
fun SomeFunction(a:Int, b:Char, c:Double) {
  // ...
}

then this function can be called in different ways

// A function that takes 3 parameters of types Int, Char, Double
fun SomeFunction(a:Int, b:Char, c:Double) {
  println("a = " + a)
  println("b = " + b)
  println("c = " + c)
}

fun main(args:Array<String>)
{
  // Calling the function SomeFunction() in different ways   
  // 1. Normal call without using named arguments   
  SomeFunction(25, 'z', 2.85)

  // 2. Calling with named parameters
  // 2.1. Named arguments are specified in the order in which   
  // the corresponding parameters are declared in the function   
  SomeFunction(a = 25, b = '+', c = 3.88)

  // 2.2. Named arguments follow in no particular order
  SomeFunction(c = 7.77, b='z', a = 33)
  SomeFunction(b = 'f', a = 100, c = 2.85)
}

 

2. Benefits of using named arguments of functions

Using named arguments when calling a function has the following advantages:

  • arguments to the function can be passed in any order. You should not remember the order of parameters when declaring a function;
  • the program code for passing arguments to a function when it is called becomes more understandable. This advantage becomes more significant when the function receives a large number of parameters or the passed variable names do not match the parameter names.

The disadvantages include an increase in the text code of the typed program in the editor.

 

3. Example of using named arguments to a function

The example declares a function that, based on the coordinates of three points (x1; y1), (x2; y2), (x3; y3), determines the area of the triangle formed from these points.

// A function that receives 6 parameters
fun AreaTriangle(x1:Double, y1:Double,
                 x2:Double, y2:Double,
                 x3:Double, y3:Double) : Double {
  val a=Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2))
  val b=Math.sqrt((x1-x3)*(x1-x3)+(y1-y3)*(y1-y3))
  val c=Math.sqrt((x2-x3)*(x2-x3)+(y2-y3)*(y2-y3))
  val p = (a+b+c)/2
  val s = Math.sqrt(p*(p-a)*(p-b)*(p-c))
  return s
}

fun main(args:Array<String>)
{
  // Calling the AreaTriangle() function with named arguments
  val s = AreaTriangle(x2=5.5, y2=3.8, x1=2.9, y1=0.5, y3=7.7, x3=10.5)
  println("s = " + s)
}

The result of the program

s = 3.179999999999992

 

4. The Nothing type. Purpose. Example

The function can return type Nothing. This means that the function does not return anything in the same way as in the case of using the Unit type. More details about the Unit type are described here.

When a function returns a Nothing (as opposed to returning a Unit), it gives the compiler the following information:

  • the function will not complete successfully. This means that the function will throw an exception or never return control to the calling code.

This need arises in the following cases:

  • when the developer of the function postpones the implementation of the function until later, because other functions or tools that this function uses have not yet been implemented;
  • when you need to specify the lines to be executed after calling a Nothing function. In this case, the compiler knows that the Nothing function will throw an exception and the lines after this function will not be executed. Lines executed after a call to the Nothing function use the result of that function, so they cannot be executed yet until this function has been finalized.

Example.

The example implements a function that returns the type Nothing.

import sun.reflect.generics.reflectiveObjects.NotImplementedException

// Function that returns type Nothing
fun MyNothingFun(number:Int) : Nothing {
  print(number)
  return throw NotImplementedError("MyNotFun error")
}

fun main(args:Array<String>)
{
  // Calling the MyNothingFun() function will throw an exception   
  MyNothingFun(25)

  // Here the compiler reports that this code will not be executed: "Unreachable code"
  print("Hello world!")
  print("bestprog.net")
}

Executing the above code throws an exception

Exception in thread "main" kotlin.NotImplementedError: MyNotFun error
at MyClass01Kt.MyNothingFun(MyClass01.kt:19)
25   at MyClass01Kt.main(MyClass01.kt:28)

After analyzing the code of the main() function in the example, you can come to the conclusion that after the MyNothingFun() function, the output lines (print(…)) will not be executed. This provides additional information (reminder) to the developer about the need to refine the MyNothingFun() function.

 


Related topics