Kotlin. Functions. Function scope

Functions. Function scope. Local scope. Default arguments in function parameters

This topic is a continuation of the topic:


Contents


Search other resources:

1. Function scope concept. Local variables. File level variables (Global Variables)

Each function declared in a program has its own scope. This area is delimited by curly braces {}, which define the body of the function. In the body of a function, various names can be used, which are the names of parameters, variables, constants or other functions. Based on this context, the compiler distinguishes between two types of variable names (constants) in a function:

  • file level names (global variables, constants). These can be, for example, the names of constants declared outside the function. You can read more about the use of constants in the program here. File-level variables must be initialized immediately after they are declared. These variables are visible anywhere in the project and exist until the entire program ends;
  • local names. Such names are the names of local variables declared in the body of the function. Relative to the local variable the term lifetime of a variable is used. If a variable is declared in the function body, then this variable has a lifetime from the moment of declaration to the closing parenthesis }.

Below is an example explaining the scope of a local variable.

// Function scope
fun MyFun() { // The function body

  // Local variables are declared here
  var x : Double // declaration of a local variable x

  // using the local variable x
  x = 2.85

  // ...

} // expiration of local variable x

In the above code, the variable x is local. The lifetime of the variable x continues from the moment it is declared until the closing parenthesis of the function. Outside the body of the function, the variable x ceases to exist.

 

2. An example demonstrating the use of file-level and local variables in the body of a function

The example declares a VolumeSphere() function that returns the volume of a sphere based on its radius. The function uses:

  • file level variable – constant Pi;
  • local variable volume, which is used to store the result of the calculation.

The function also uses the radius parameter, which has the same scope as the local variable volume.

// File level variable
const val Pi = 3.1415

// A function that calculates the volume of a sphere for a given radius
fun VolumeSphere(radius : Double):Double {
  val volume : Double // local variable
  volume = 4.0/3*Pi*radius*radius*radius
  return volume
}

fun main(args:Array<String>)
{
  // Using the VolumeSphere() function

  // 1. Declare variables
  val r : Double
  val result : Double

  // 2. Input radius
  print("radius = ")
  r = readLine().toString().toDouble()

  // 3. Call the function
  result = VolumeSphere(r)

  // 4. Display the result
  print("result = " + result)
}

Test example

radius = 3.5
result = 179.58908333333332

 

3. Default arguments. Features of use

There are times, when declaring a function, one or more parameters must receive some initial, most common, values. When the function is called, these initial values can be changed to others, depending on the need.

Therefore, the default values set for the parameters of a function when it is declared are called default arguments.

The general form of a function declaration containing one parameter that receives a default argument is as follows

fun FuncName(paramName : Type = value) : Type {
  // ...
}

here

  • FuncName – function name;
  • paramName – parameter name;
  • Type – parameter type;
  • value – the default value that the paramName parameter receives.

After such a declaration, the function can be called in two ways. The first way is to call with an explicit argument

FuncName(argument)

Another way is to call with no arguments

FuncName()

With this method, instead of an argument, the function body is substituted with the value that is specified in the paramName parameter when the function is declared

paramName : Type = value

The general form of declaring a function that takes N arguments by default is

fun FuncName(paramName1 : Type1 = value1,
             paramName2 : Type2 = value2,
             ...
             paramNameN : TypeN = valueN,
            ) : Type {
  // ...
}

here

  • paramName1, paramName2, paramNameN – names of parameters that have types Type1, Type2, TypeN respectively, and receive the values value1, value2, valueN, respectively.

 

4. Restrictions on the use of default arguments

When declaring a function with several default arguments, you need to adhere to the following rule: parameters that do not receive default values follow first, followed by parameters that receive default values. The point is that the compiler passes the first passed argument to the first parameter anyway. This means that the second or other next parameter will not receive any value, which will lead to an error at the compilation stage.

For example.

Let the following erroneous function declaration be given

fun MyFun(param1 : Int = 2, param2 : Double) {
  println(param1)
  println(param2)
}

In this case, the call to the MyFun() function is limited

...

MyFun(3, 2.2) // Works, both parameters take a value.
MyFun()  // Error. You need to set param2.
MyFun(2) // Error. The value is set to param1. Param2 is undefined. 

...

 

5. Examples of declaring and using functions containing default arguments
5.1. Calculating the distance between two points

Task. Develop and demonstrate the operation of a function that calculates the distance between two points given by coordinates (x1; y1) and (x2; y2). When declaring a function, set the following default point values

x1 = 0
y1 = 0
x2 = 1
y2 = 1

Solution.

// A function that calculates the distance between two points // given by coordinates (x1; y1), (x2; y2).
fun Length(x1 : Double = 0.0, y1 : Double = 0.0,
    x2 : Double = 1.0, y2 : Double = 1.0) : Double {
  return Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2))
}

fun main(args:Array<String>)
{
  // Demonstration of using the Length() function

  // Calculate the length for the points (0, 0), (1, 1)
  println("(0,0)-(1,1) = " + Length())

  // Calculate the length for the points (0, 0), (2, 2)
  println("(0,0)-(2,2) = " + Length(0.0, 0.0, 2.0, 2.0))

  // Calculate the length for the points (3, 4), (1, 1)
  println("(3,4)-(1,1) = " + Length(3.0, 4.0))

  // Calculate the length for the points (2, 0), (1, 1)
  println("(2,0)-(1,1) = " + Length(2.0))
}

Program result

(0,0)-(1,1) = 1.4142135623730951
(0,0)-(2,2) = 2.8284271247461903
(3,4)-(1,1) = 3.605551275463989
(2,0)-(1,1) = 1.4142135623730951

 

5.2. Complex number modulus

Task. Implement the AbsComplex() function, which receives as parameters the real and imaginary parts of a complex number. Function parameters are assigned single default values.

Solution.

// Function that calculates the modulus of a complex number
fun AbsComplex(re:Double = 1.0, im:Double = 1.0) : Double {
  return Math.sqrt(re*re+im*im)
}

fun main(args:Array<String>)
{
  // Demonstration of using the AbsComplex() function

  // Calculate the modulus of a complex number 1 + 1*j
  println("|1 + j| = " + AbsComplex())

  // The modulus of number 3 - 2*j
  println("|3 - 2*j| = " + AbsComplex(3.0,-2.0))

  // The modulus of number 2 + j
  println("|2 + 1*j| = " + AbsComplex(2.0))

  // The modulus of number 1 + 2*j
  println("|1 + 2*j| = " + AbsComplex(1.0, 2.0))
}

Program result

|1 + j| = 1.4142135623730951
|3 - 2*j| = 3.605551275463989
|2 + 1*j| = 2.23606797749979
|1 + 2*j| = 2.23606797749979

 


Related topics