In Scala, it is very easy to chain function calls by using functional composition. By combining pure functions in this way, we can compose many functions in a very concise and easily testable manner.
Functions that are declared using the val keyword inherit both the compose and andThen functions (they do the same thing, the order is just reversed). This allows us to easily compose functions.
Calling compose will take the result of the second function and pass it as a parameter to the first function.
Calling andThen will take the result of the first function and pass it as a parameter to the second function.
val square: Int => Int = x => x * x val increment: Int => Int = x => x + 1 val composedExample: Int => Int = square compose increment
Calling composedExample with an integer value would evaluate to square(increment(x)), so we would first increment, and then square the number:
scala> composedExample(5) res0: Int = 36
Alternatively, we could use the andThen function to achieve g(f(x)):
val square: Int => Int = x => x * x val increment: Int => Int = x => x + 1 val andThenExample: Int => Int = square andThen increment
Calling andThenExample with an integer value would evaluate to increment(square(x)), so we would first square, and then increment the number:
scala> andThenExample(5) res1: Int = 26
When working with methods declared using the def keyword, we can easily convert them into functions using the ‘_‘ symbol:
def square(x: Int): Int = x * x def increment(x: Int): Int = x + 1 val composedDefExample: Int => Int = square _ compose increment _ val andThenDefExample: Int => Int = square _ andThen increment _ scala> composedDefExample(5) res2: Int = 36 scala> composedDefExample(5) res3: Int = 26
TL;DR: Functional composition is a very easy concept that can be used to chain function calls, making code much more concise.
f(x) compose g(x) gives us f(g(x))
f(x) andThen g(x) using gives us g(f(x))