Declaring Functions in Scala

    A function is a piece of code designed to do some computation. It can be defined with no parameters or single or many parameters. It may return a unit (side effects - not recommended) or a value. It can be assigned to a variable in Scala to store the value returned after computation.

    The basic syntax of a function:

    def nameOfFunction(functionParameter1 : ParameterType, …..): = ReturnType = {
        val result = // function Body
        result //If you notice we have not used return keyword here because it is not mandatory in Scala
    }

    Note : A function which don't have ( := { <Body_of_Function> }) will be an abstract function

    There can be different types of functions:

    Anonymous Function

    A function that doesn’t have a name is called an Anonymous function.

    Example

    x: Int) => x + 1
    
    X is parameter to function and (x+1) defines body of function. To define more than one statement, we must enclose them in curly braces.
    (x: Int) => {
        val y = x+1;
        y*2;
    }

    Named Function

    A function that has a name is called a Named function.

    Example

    val decrement = (number: Int) => number -1

    Here you can see we can assign a function to a value.

    Usage of the above example:

    println(decrement(5))    // this internally will evaluate like decrement.apply(5)

    All functions in Scala are special objects of Function1 or Function2, or FunctionN, where N is the number of input arguments to the function. The compiler will automatically box our function code into the appropriate object. This object contains a method apply() that can be called to execute our function.

    Methods

    It is a type of function that is part of a class, can be overridden, and can use a different syntax(overloaded). Scala doesn’t allow us to define an anonymous method. These are created using a special keyword “def”.

    Example

    def greetSomeone(name: String): String =   s"Welcome to + $name"
    
    greetSomeone("Techgeekbuzz!")

    Nested Method

    When a method is defined inside another method, it is called a nested method.

    Example:

    def tailRecursiveFactorial(number: BigInt): BigInt = {
      def fact(number: BigInt, result: BigInt): BigInt = {
        if(number == 1) result
        else fact(number-1, number*result)
      }
      fact(number, 1)
    }
    tailRecursiveFactorial(10000)

    Higher Order Function

    A function that can be passed as a value to a function or a function that can be returned as a value from a function can be termed a Higher Order Function

    Example:

    The map function defined on List is a higher-order function. The syntax for the same is given below:

    final override def map[B](f : scala.Function1[A, B]) : scala.collection.immutable.List[B]
    List(1,2,3).map(_.*3)  

    Output

    List(3,6,9)

    Here[ _.*3 ] is a function that will multiply the element by 3. This function is passed into the map function and is an example of a higher-order function.

    Similar examples of the Higher Order function in the List class are below:

    override def filter(p : scala.Function1[A, scala.Boolean]) : scala.collection.immutable.List[A]
    
    override def partition(p : scala.Function1[A, scala.Boolean]): scala.Tuple2[scala.collection.immutable.List[A], scala.collection.immutable.List[A]] = { /* compiled code */ }