Explore the fundamentals of functional programming in Scala. Learn about pure functions, immutability, recursion, tail recursion, and function composition through 30 MCQs that enhance your Scala skills.
Functional Programming Basics in Scala
1. Pure Functions and Immutability
What is a characteristic of a pure function in Scala?
A) It modifies its input
B) It always produces the same output for the same input
C) It does not return any value
D) It depends on external state
Which of the following is true about immutability in Scala?
A) Mutable data can be shared between threads safely
B) Immutable data cannot be changed after it is created
C) Immutability is not supported in Scala
D) Immutability applies only to primitive data types
Which of the following best describes the benefit of using pure functions in Scala?
A) They are faster than impure functions
B) They avoid side effects and are easier to test
C) They require mutable data to function
D) They interact with external states
Which of the following is an example of a pure function?
A) def sum(a: Int, b: Int): Int = a + b
B) def printMessage(msg: String): Unit = println(msg)
C) def updateGlobalState(value: Int): Unit = { globalState = value }
D) def getDate: String = new Date().toString
How does immutability help with functional programming?
A) It prevents the accidental modification of data
B) It enables mutable state management
C) It simplifies multi-threading by avoiding synchronization
D) It eliminates the need for recursion
Which of the following is a feature of functional programming in Scala?
A) Use of global mutable state
B) Immutability and avoidance of side effects
C) Classes with mutable fields
D) Loop-based control structures
What is the main advantage of using immutable data structures in Scala?
A) They improve performance by reducing memory usage
B) They ensure that data cannot be changed accidentally, improving safety in concurrent environments
C) They are easier to serialize
D) They increase complexity in handling large datasets
In functional programming, why is it important to use pure functions?
A) They enable state modification
B) They reduce complexity and make reasoning about programs easier
C) They make the program faster
D) They prevent the use of recursion
Which of the following data types is inherently immutable in Scala?
A) String
B) List
C) Option
D) All of the above
What happens when you try to modify an immutable object in Scala?
A) The object is modified in place
B) A new object is created with the updated value
C) An exception is thrown
D) The value remains unchanged
2. Recursion and Tail Recursion
What is recursion in functional programming?
A) Repeatedly applying a function to itself until a base case is reached
B) Using loops to repeat an operation
C) Modifying variables in a loop to achieve a result
D) Applying the same function repeatedly to different data
Which of the following is a key feature of tail recursion?
A) The recursive call is the last action performed in the function
B) The function must return a result before the recursive call
C) The recursion has no base case
D) Tail recursion is not allowed in Scala
How does Scala optimize tail-recursive functions?
A) By storing the result of each recursive call in a stack
B) By reusing the stack frame for each recursive call
C) By disabling recursion altogether
D) By calling the recursive function asynchronously
Which of the following Scala functions is tail-recursive?
A) def factorial(n: Int): Int = if (n == 0) 1 else n * factorial(n - 1)
B) def factorial(n: Int, accumulator: Int = 1): Int = if (n == 0) accumulator else factorial(n - 1, n * accumulator)
C) def factorial(n: Int): Int = if (n == 0) 0 else n * factorial(n - 1)
D) def factorial(n: Int): Int = if (n == 0) n else n * factorial(n - 1)
What is the primary benefit of using tail recursion in Scala?
A) It allows recursion without the risk of stack overflow
B) It prevents side effects in recursive functions
C) It simplifies the function signature
D) It improves memory consumption by avoiding function calls
Which of the following functions will result in a stack overflow error for large input sizes?
A) Tail-recursive function
B) Non-tail-recursive function
C) A function with mutable state
D) A function using map and filter
In Scala, how can you ensure that a recursive function is tail-recursive?
A) By making sure the recursive call is the last expression in the function
B) By using a while loop before the recursion
C) By checking for the base case early in the function
D) By avoiding recursion altogether
How does Scala’s @tailrec annotation help in recursion?
A) It prevents tail recursion from being optimized
B) It marks a function for optimization as a tail-recursive function
C) It turns non-tail-recursive functions into tail-recursive ones
D) It prevents recursion from happening
Which of the following is NOT a characteristic of tail recursion?
A) The function reuses its stack frame
B) The recursion continues until the base case is reached
C) The function must perform computation after the recursive call
D) The recursive call is the last thing the function does
What is the time complexity of a tail-recursive function in Scala?
A) O(n)
B) O(log n)
C) O(1)
D) O(n^2)
3. Function Composition
What does function composition in Scala refer to?
A) Combining multiple functions to form a new function
B) Combining multiple variables to form a new function
C) Overriding functions to create new ones
D) Changing the type of a function
How can two functions f and g be composed in Scala?
A) By calling f(g(x))
B) By calling g(f(x))
C) By using the andThen or compose method
D) By merging the functions into one
Which of the following is the correct method for function composition in Scala?
A) f compose g
B) f + g
C) f and g
D) f || g
What does the andThen method do in function composition?
A) It applies the function f first, then applies function g to the result
B) It applies the function g first, then applies function f to the result
C) It applies g and f in parallel
D) It returns the function with the highest precedence
What is the primary advantage of function composition in Scala?
A) It allows for complex operations to be broken down into smaller, reusable functions
B) It improves performance by merging functions
C) It eliminates the need for higher-order functions
D) It makes recursive functions easier to implement
Which of the following is an example of function composition?
A) val add1 = (x: Int) => x + 1 and val multiply2 = (x: Int) => x * 2; add1 andThen multiply2
B) val add1 = (x: Int) => x + 1 and val multiply2 = (x: Int) => x * 2; add1 + multiply2
C) val add1 = (x: Int) => x + 1 and val multiply2 = (x: Int) => x * 2; add1 > multiply2
D) val add1 = (x: Int) => x + 1 and val multiply2 = (x: Int) => x * 2; add1 or multiply2
Which function composition operator applies f first and then g in Scala?
A) andThen
B) compose
C) |>
D) +
What is the main benefit of function composition in functional programming?
A) It reduces code duplication and promotes reusability
B) It allows for mutable state to be shared
C) It simplifies the understanding of the program flow
D) It improves memory management
Which of the following is a result of composing functions in Scala?
A) A new function that applies both functions sequentially
B) A single function that overrides both functions
C) A new function that randomly applies either of the two functions
D) A new function that applies one function after the other without any interaction
Which of the following can be composed using andThen or compose?
A) Functions of the same signature
B) Functions of different signatures
C) Functions with mutable state
D) Functions with no return type
Answer Key
Qno
Answer (Option with the text)
1
B) It always produces the same output for the same input
2
B) Immutable data cannot be changed after it is created
3
B) They avoid side effects and are easier to test
4
A) def sum(a: Int, b: Int): Int = a + b
5
A) It prevents the accidental modification of data
6
B) Immutability and avoidance of side effects
7
B) They ensure that data cannot be changed accidentally, improving safety in concurrent environments
8
B) They reduce complexity and make reasoning about programs easier
9
D) All of the above
10
B) A new object is created with the updated value
11
A) Repeatedly applying a function to itself until a base case is reached
12
A) The recursive call is the last action performed in the function
13
B) By reusing the stack frame for each recursive call
14
B) def factorial(n: Int, accumulator: Int = 1): Int = if (n == 0) accumulator else factorial(n - 1, n * accumulator)
15
A) It allows recursion without the risk of stack overflow
16
B) Non-tail-recursive function
17
A) By making sure the recursive call is the last expression in the function
18
B) It marks a function for optimization as a tail-recursive function
19
C) The function must perform computation after the recursive call
20
A) O(n)
21
A) Combining multiple functions to form a new function
22
C) By using the andThen or compose method
23
A) f compose g
24
A) It applies the function f first, then applies function g to the result
25
A) It allows for complex operations to be broken down into smaller, reusable functions
26
A) val add1 = (x: Int) => x + 1 and val multiply2 = (x: Int) => x * 2; add1 andThen multiply2
27
A) andThen
28
A) It reduces code duplication and promotes reusability
29
A) A new function that applies both functions sequentially