FP has the following principles:
- Pure functions
- Immutable data
- No side effects
- Referential transparency (RT)
- Functions are first-class citizens
- Functions that include anonymous functions, higher order functions, combinators, partial functions, partially-applied functions, function currying, closures
- Tail recursion
- Functions composability
We will discuss these principles or properties of FP in brief here because we have a dedicated chapter on these concepts. Refer to Chapter 2, Functional Scala, to understand these concepts in-depth with some simple examples.
A pure function is a function that always returns the same results for the same inputs irrespective of how many times and where you run this function.
We will get lots of benefits with immutable data. For instance, no shared data, no side effects, thread safety for free, and so on.
Like an object is a first-class citizen in OOP, in FP, a function is a first-class citizen. This means that we can use a function as any of these:
- An object
- A value
- A data
- A data type
- An operation
In simple words, in FP, we treat both functions and data as the same.
We can compose functions that are in sequential order so that we can solve even complex problems easily. Higher-Order Functions (HOF) are functions that take one or more functions as their parameters or return a function as their result or do both.
For instance, map(), flatMap(), filter(), and so on are some of the important and frequently used higher-order functions. Consider the following example:
map(x => x*x)
Here, the map() function is an example of Higher-Order Function because it takes an anonymous function as its parameter. This anonymous function x => x *x is of type Int => Int, which takes an Int as input and returns Int as its result.
An anonymous function is a function without any name.
Refer to Chapter 2, Functional Scala, to understand these concepts very well. I have provided a useful description and also some simple and easy-to-understand examples.