
- Scala - Home
- Scala - Overview
- Scala - Features
- Scala - Environment Setup
- Scala - Build Tool (SBT)
- Scala - REPL
- Scala - Dot & Dotty
- Scala - Basic Syntax
- Scala - Hello World Program
- Scala - Identifiers
- Scala - Keywords
- Scala - Comments
- Scala - Code Blocks
- Scala - Semicolon
- Scala - Constructs
- Scala - Expressions
- Scala - Input and Output
- Scala - Optional Braces
- Scala - Underscore (_)
- Data Types and Variables
- Scala - Data Types
- Scala - Type Bounds
- Scala - Context Bound
- Scala - Variances
- Scala - Type Hierarchy
- Scala - Variables
- Scala - Variable Scopes
- Scala - Literals
- Scala - Numeric Types
- Scala - Boolean Types
- Scala - Char Type
- Scala - Unit Types
- Scala - Strings
- Scala - Arrays
- Scala - Null Type
- Scala - Nothing
- Scala - Any Type
- Scala - AnyRef Type
- Scala - Unified Types
- Scala - Dates and Times
- Scala - Ranges
- Scala - Multidimensional Arrays
- Scala - WrappedArray
- Scala - StringBuilder
- Scala - String Interpolation
- Scala - StringContext
- Scala - Type Casting
- Scala var vs val
- Scala Operators
- Scala - Operators
- Scala - Rules for Operators
- Scala - Arithmetic Operators
- Scala - Relational Operators
- Scala - Logical Operators
- Scala - Bitwise Operators
- Scala - Assignment Operators
- Scala - Operators Precedence
- Scala - Symbolic Operators
- Scala - Range Operator
- Scala - String Concatenation Operator
- Scala Conditional Statements
- Scala - IF ELSE
- Scala - IF-ELSE-IF-ELSE Statement
- Scala - Nested IF-ELSE Statement
- Scala Loop Statements
- Scala - Loop Statements
- Scala - while Loop
- Scala - do-while Loop
- Scala - Nested Loops
- Scala - for Loop
- Scala - break Statement
- Scala - yield Keyword
- Scala Classes & Objects
- Scala - Classes & Objects
- Scala - Constructors
- Scala - Auxiliary Constructor
- Scala - Primary Constructor
- Scala - This Keyword
- Scala - Nested Classes
- Scala - Getters and Setters
- Scala - Object Private Fields
- Scala - Singleton Object
- Scala - Companion Objects
- Scala - Creating Executable Programs
- Scala - Stateful Object
- Scala - Enumerations
- Scala - Polymorphism
- Scala - Access Modifiers
- Scala - Apply Method
- Scala - Update Methods
- Scala - UnapplySeq Method
- Scala - Inheritance
- Scala - Extending a Class
- Scala - Method Overloading
- Scala - Method Overriding
- Scala - Generic Classes
- Scala - Generic Functions
- Scala - Superclass Construction
- Scala Methods & Functions
- Scala - Functions
- Scala - Main Methods
- Scala - Functions Call-by-Name
- Scala - Functions with Named Arguments
- Scala - Function with Variable Arguments
- Scala - Recursion Functions
- Scala - Default Parameter Values
- Scala - Functions without Parameters
- Scala - Implicit Parameters
- Scala - Higher-Order Functions
- Scala - Nested Functions
- Scala - Extension Methods
- Scala - Anonymous Functions
- Partially Applied Functions
- Scala - Lazy Val
- Scala - Pure Function
- Scala - Currying Functions
- Scala - Control Abstractions
- Scala - Corecursion
- Scala - Unfold
- Scala - Tail Recursion
- Scala - Infinite Sequences
- Scala - Dynamic Invocation
- Scala - Lambda Expressions
- Scala Collections
- Scala - Collections
- Mutable and Immutable Collections
- Scala - Lists
- Scala - Sets
- Scala - Maps
- Scala - TreeMap
- Scala - SortedMap
- Scala - Tuples
- Scala - Iterators
- Scala - Options
- Scala - Infinite Streams
- Scala - Parallel Collections
- Scala - Algebraic Data Types
- Scala Pattern Matching
- Scala - Pattern Matching
- Scala - Type Patterns
- Scala - Exception Handling
- Scala - Extractors
- Scala - Regular Expressions
- Scala Files I/O
- Scala - Files I/O
- Scala Advanced Concepts
- Scala - Closures
- Scala - Futures
- Scala - Promises
- Scala - Traits
- Scala - Trait Mixins
- Scala - Layered Traits
- Scala - Trait Linearization
- Scala - Sealed Traits
- Scala - Transparent Traits
- Scala - Literal Type Arithmetic
- Scala - Inline keyword
- Scala - Def, Var & Val
- Scala - Dropped Features
- Scala - BDD Testing
Scala - Recursion Functions
Recursion is a technique in which a function calls itself in order to solve a problem. Recursion is used as an alternative to iteration for tasks like traversing data structures, performing calculations, and solving complex problems.
Recursive Functions
Recursive function is a function that calls itself in its definition. Recursive functions call themselves to solve a problem by breaking down a big problem into smaller sub-problems. Recursion can be direct and indirect. Direct recursion occurs when the function calls itself directly. Indirect recursion occurs when the function calls another function that eventually calls the original function.
Basic Concept
Recursive function is defined similarly to a regular function, but it calls itself. So recursive functions must have a base case to prevent infinite recursion and stop. There are two parts of recursive functions:
- Base Case: Function stops calling itself to prevent infinite recursion.
- Recursive Case: Function calls itself with modified arguments and moves towards the base case.
Factorial: Example of Recursive Function
The factorial of a non-negative integer n is the product of all positive integers less than or equal to n. It can be defined recursively as:
- factorial(0) = 1 (base case)
- factorial(n) = n * factorial(n - 1) (recursive case)
Syntax
The syntax of recursive function is -
def functionName(parameters): ReturnType = { if (baseCondition) { // base case baseResult } else { // recursive case functionName(modifiedParameters) } }
Example
The following example shows a simple recursive function to calculate the factorial of a number -
def factorial(n: Int): Int = { if (n == 0) 1 // base case else n * factorial(n - 1) // recursive case } object Demo { def main(args: Array[String]) = { println("Factorial of 5: " + factorial(5)) } }
Save the above program in Demo.scala. The following commands are used to compile and execute this program.
Command
> scalac Demo.scala > scala Demo
Output
Factorial of 5: 120
In the example, the factorial function calculates the factorial of a given number n. The function uses base case (n == 0) to return 1. The recursive case (n * factorial(n - 1)) to multiply n by the factorial of n - 1.
Tail Recursion
Tail recursion is a special form of recursion where the recursive call is the last operation in the function. Since there is no advantage of tail recursive function over iterative function. So
Tail-recursive functions are optimized by the Scala compiler to prevent stack overflow and improve performance.
Syntax
Tail-recursive function can be defined using the @tailrec annotation. It ensures that the function is optimized by the compiler.
import scala.annotation.tailrec @tailrec def functionName(parameters): ReturnType = { if (baseCondition) { // base case baseResult } else { // recursive case functionName(modifiedParameters) } }
Example
The following example shows a tail-recursive function to calculate the factorial of a number -
import scala.annotation.tailrec def factorial(n: Int): Int = { @tailrec def factorialHelper(x: Int, accumulator: Int): Int = { if (x == 0) accumulator else factorialHelper(x - 1, x * accumulator) } factorialHelper(n, 1) } object Demo { def main(args: Array[String]) = { println("Factorial of 5: " + factorial(5)) } }
Save the above program in Demo.scala. The following commands are used to compile and execute this program.
Command
> scalac Demo.scala > scala Demo
Output
Factorial of 5: 120
In the example, the factorial function has helper function factorialHelper. It is tail-recursive. The factorialHelper function takes parameter accumulator to accumulate the result. The @tailrec annotation ensures that the function is optimized by the Scala compiler.
Recursion vs Iteration
These are some differences between recursive and iterative programs in Scala -
Aspect | Recursive Approach | Iterative Approach |
---|---|---|
Definition | A function that calls itself directly or indirectly until a base condition is met. | Loops that repeat a block of code until a specific condition is false. |
Execution | Typically has more overhead due to repeated function calls and stack management. | Generally more efficient as it avoids repeated function calls and manages variables in a loop structure. |
Complexity | Can be simpler to implement for certain problems, especially those naturally recursive (e.g., tree traversal). | Requires careful management of loop variables and termination conditions. |
Memory Usage | May consume more memory due to maintaining a call stack for each recursive call until base case is reached. | Generally consumes less memory as it uses iterative constructs like while or for loops. |
Readability | Can be easier to understand for problems inherently recursive (e.g., factorial calculation). | May require a deeper understanding of loop constructs but can be straightforward for iterative tasks. |
Tail Recursion | Tail recursive functions can be optimized by the compiler to avoid stack overflow. | Not applicable, as iterative loops inherently manage stack space without overflow risks. |
Examples | Calculating factorial, tree traversal, Fibonacci series. | Summing elements in a list, iterating over collections, matrix operations. |
Example: Sum of Natural Numbers
Both recursion and iteration can be used to calculate the sum of the first n natural numbers in Scala -
Recursive
def sum(n: Int): Int = { if (n == 0) 0 else n + sum(n - 1) } object Demo { def main(args: Array[String]) = { println("Sum of first 5 natural numbers: " + sum(5)) } }
Iterative
def sum(n: Int): Int = { var total = 0 for (i <- 1 to n) { total += i } total } object Demo { def main(args: Array[String]) = { println("Sum of first 5 natural numbers: " + sum(5)) } }
Save the above program in Demo.scala. The following commands are used to compile and execute this program.
Command
> scalac Demo.scala > scala Demo
Output
Sum of first 5 natural numbers: 15
In the recursive version, the sum function calculates the sum of the first n natural numbers using a base case (n == 0) to return 0. Recursive case (n + sum(n - 1)) to add n to the sum of n - 1 numbers.
In the iterative version, the sum function calculates the sum using a for loop to iterate through the numbers from 1 to n. So, accumulating the total in the total variable.
Recursive Function Summary
- Recursive functions in Scala call themselves to solve problems. Recursive functions break down a big problem into smaller sub-problems.
- Recursive functions can be used to traverse and manipulate data structures, like lists and trees.
- Tail recursion is a special case of recursion where the recursive call is the last operation. So optimization and preventing stack overflow errors.
- Recursive functions have advantages in simplicity and modularity. But can have disadvantages in performance and risk of stack overflow.