This is a moment for my first real post. For start I wanted to write on some topic that I feel rather comfortable, so I went for functional programming. I'll try to give you some introduction to this interesting topic. Some concepts that will be described, will be followed by example in Scala, which is my language of choice for FP.
Functional programming can be probably defined in many ways. I'd say that it is a paradigm that enforces usage of the following two principles (I believe that they are foundations of FP):
- usage of functions (also higher-order* ones) as first class citizens - so that they are the basic construction blocks for building a computer program.
- avoidance of mutable state, side-effects or assignment statements.
Firstly I'd like to focus on the first one. This principle is very attractive to me, as my favourite programming principle is:
Encapsulate what varies
I believe that many people identify encapsulation with the process of hiding representation of some object's data. I think that's a mistake, as hiding behaviour is at least as important as hiding data representation. Easy way to create/pass/use functions helps you achieve that in a pretty convenient mannner.
Scala's way to work with functions is very effective, which is typical for a FP language. But in some other languages like Java you usually need to explicitly create a separate interface. One can think that it takes a bit more effort than it actually should.
I believe that usage of functions is particulary useful when you work with collections. In Scala you can easily process them as they offer you following operations:
- map - translates from one representation to another
- filter - selects only elements that match given predicate
- reduce/fold - combines elements of the collection to a single object
There are people that call them the functional operators, as these ideas are very common in functional programming. Theirs example usage is shown in the snippet below.
Another principle that is at the very core of functional programming is:
Data immutability means that one object, once created, will not have its state changed. This is particular useful if you try to write some parallel, multi-threaded code. You see, when data is never going to change, there is no need for synchronizing access to this data. And when synchronization oriented concerns disappear, developer has a lot less to worry about.
In FP language, it is feasible to work on immutable data as there are useful techniques available to create copies of the object that differs with some specified property. This is illustrated below.
When you do a functional programming you might think that recursion is closer to those principles than iteration. The latter is usually connected with mutable state, while recursion avoids it as much as it can. One can argue that iteration is more effective than recursion, but there's a technique that allows recursion to match iteration's performance. This technique is called tail-recursion and is offered in Scala. I am not going to describe its specifics now, as it is quite far from intended topic of the post.
People can question, like I do, if you can totally avoid mutable state in programming. I'd say that in real-world applications you can't (or shouldn't). But if there is actually genuine need for it, then there are tools to support you with that. One such tool is an actor (or whole actor system) that would allow you to synchronize access and operations on some data. Actors are often used in Scala with a library called Akka. One day I'll definitely write about Akka.
There is still more
In this post I've described the principles that I believe are fundamental to functional programming. Particular FP languages like Scala offers other features that I feel support FP even more, like: Option type, pattern matching, lazy evaluation and implicit parameters/conversions. If you are interested in the topic, I would encourage you to try those things as well.
*higher-order functions are functions that take other functions as arguments or return them