Recursion in Scala

Recursion is a method which breaks the problem into smaller sub problems and calls itself for each of the problems. That is, it simply means function calling itself. We can use recursion instead of loops. Recursion avoids mutable state associated with loops. Recursion is quite common in functional programming and provides a natural way to describe many Algorithms. Recursion is considered as to be important in functional programming. Scala supports Recursion very well.

Let us understand using the simple factorial example.
Example :

filter_none

edit
close

play_arrow

link
brightness_4
code

// Scala program of factorial using recursion
  
// Creating object
object GFG
{
    // Function define
    def fact(n:Int): Int=
    {
        if(n == 1) 1
        else n * fact(n - 1)
    }
      
    // Main method
    def main(args:Array[String])
    {
        println(fact(3))
    }
}

chevron_right


Output:

6

The above code demonstrated in a recursive approach to a factorial function, where the condition n == 1 results in a break from the recursion.

Let us understand more clearly by an example of gcd.
Example :

filter_none

edit
close

play_arrow

link
brightness_4
code

// Scala program of GCD using recursion
  
// Creating object
object GFG
{
    // Function defined
    def gcd(x:Int, y:Int): Int=
    {
        if (y == 0) x
        else gcd(y, x % y)
    }
      
    // Main method
    def main(args:Array[String])
    {
        println(gcd(12, 18))
    }
}

chevron_right


Output:

6

Problem with recursion is that deep recursion can blow up the stack if we are not careful.
Let’s understand this by using an example:
Example Code:

filter_none

edit
close

play_arrow

link
brightness_4
code

// Scala program of sum all numbers
// using recursion
   
// Creating object
object GFG
{
    // Function defined
    def sum(num: Int): Int=
    {
        if (num == 1)
            1
        else
            sum(num - 1) + num
    }
      
    // Main method
    def main(args:Array[String])
    {
        println(sum(55))
    }
}

chevron_right


Output:

1540

The method sum will do the summation of all the numbers. We reduce the num everytime and add it to the result. Here, whenever we call sum, it will leave input value num on the stack and using up memory every time. when we try passing a large input like sum(555555) than the output will be java.lang.StackOverflowError. This output means that the stack has been blown up.

The above example does not use tail recursion and is therefore not an optimal approach, especially if the starting value n is very large.

Tail Recursion

The tail recursive functions considered better than non tail recursive functions as tail-recursion can be optimized by compiler. A recursive function is said to be tail recursive if the recursive call is the last thing done by the function. There is no need to keep record of the previous state.
Let us understand it by a example:

Example :

filter_none

edit
close

play_arrow

link
brightness_4
code

// Scala program of factorial using tail recursion
import scala.annotation.tailrec
  
// Creating object
object GFG
{
    // Function defined
    def factorial(n: Int): Int =
    {
        // Using tail recursion
        @tailrec def factorialAcc(acc: Int, n: Int): Int =
        {
            if (n <= 1)
                acc
            else 
                factorialAcc(n * acc, n - 1)
        }
        factorialAcc(1, n)
    }
      
    // Main method
    def main(args:Array[String])
    {
        println(factorial(5))
    }
}

chevron_right


Output:

120

Here in the above code, we can use the @tailrec annotation to confirm that our algorithm is tail recursive.

If we use this annotation and our algorithm isn’t tail recursive, the compiler will complain. For instance, if we attempt to use this annotation on the above example of the factorial method, we will get the following compile-time error.

Example :

filter_none

edit
close

play_arrow

link
brightness_4
code

// Scala program of factorial with tail recursion
import scala.annotation.tailrec
  
// Creating object
object GFG
{
    // Function defined
    @tailrec def factorial(n: Int): Int =
    {
        if (n == 1)
            1
        else 
            n * factorial(n - 1)
    }
      
    // Main method
    def main(args:Array[String])
    {
        println(factorial(5))
    }
}

chevron_right


Output:

Could not optimize @tailrec annotated method factorial: it contains a recursive call not in tail position


My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.




Article Tags :

Be the First to upvote.


Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.