Functional programmers often look down upon conventions and approaches used in imperative programming, like the usage of mutable variable, the usage of for loops, the creation of explicit exceptions.
However if one digs deep into Scala's library one would discover that the language's functional elegance is actually encapsulated by a semi imperative implementation.
For example, consider the implementation of forall
in the TraversableLike trait.
def forall(p: A => Boolean): Boolean = {
var result = true
breakable {
for (x <- this)
if (!p(x)) { result = false; break }
}
result
}
It is easy to argue that all functional languages are high level languages and are actually built on an imperative base, as in the language itself was built using an imperative language.
However, my question is where should one draw the like between imperative and functional styles in order to keep the code base compliant with functional standards ?
This is mainly an opinionated question, so I will give an opinionated answer.
Scala is a language that allows imperative/OOP programmers, especially Java programmers, to discover functional programming. As such, it allows coders to do everything as they would do in Java, but gives them the possibility (and the community encourages them) to do functional programming too.
Once you are set on using Scala as a functional programming language, you should ALMOST never use imperative elements such as var
s, return
and while
loops.
Most of your programming should be done in a functional way, to allow all the advantages of such a paradigm (wich are not the subject of the question, so I will not dwell on this matter).
However, you cannot forget the fact that, deep down, the computers on which the code is run, or the JVM, are fundamentally imperative in the sense that you give instructions which change the state of the memory (you cannot make it any less functional!).
Therefore, for performance reasons, it is sometimes better to use imperative elements, but this should be done in the most controlled and encapsulated way possible. This is in particular the case of the standard scala library, but might be also used in some part of any developper's code when the need arises.
One fine example is the use of var
in an akka Actor
. Since actors are supposed to be single units of concurrent computation, they can have an intrisic mutable state, which will be encapsulated by the very principle of actor systems (which states that you can only talk to an actor by the mean of messages), so this state will not risk concurrent access/mutation (which is the main problem with mutable values in my opinion).