Every functional programmer should write an article about what FP is at all and I’m not an exception. Next step should be another monad tutorial – and it’s still on it’s way.
Introduction to functional programming
1 2 3 4 5 6 7 8 9 10 11 12 13
So, let’s put a couple of definition:
- Functional language is a programming language which enables, encourages or even enforces functional programming.
- Functional features are features of a programming language or a library, which makes functional programming easier
- Functional programming is… well, let’s talk about that below
A functional language as a tool use functional features to make using functional programming as a paradigm easier; and we can use those definitions to determine if some programming language is a functional language or not. Whew, enough of F-word :)
But we have one more definition to fill up – functional programming or functional paradigm (FP). This is done by contrast usually and I will follow that path, but with one small deviation. Usually FP is being compared to imperative programming whatever it means. Also is being said that FP and OOP are orthogonal and don’t deny each other. I’m going to argue with that. So, before going to FP lang, let’s see what we have in OOP.
Here’s a definition given by Alan Key:
1. Everything is an object.
2. Objects communicate by sending and receiving messages (in terms of objects).
3. Objects have their own memory (in terms of objects).
4. Every object is an instance of a class (which must be an object).
5. The class holds the shared behavior for its instances (in the form of objects in a program list)
What’s interesting here is #2 and #3. Objects communicate by sending and receiving objects, for example:
That’s valid Ruby code, which sends a message
full_name to object
user and writes response to
result variable. Of course, there’s a
shorter version, which is in fact a syntactic sugar:
It doesn’t matter if we’re talking about static or dynamic languages, Java, C#, Ruby, Smalltalk or Python – every method call can be presented as sending a message. We can see simplest basic blocks of OOP are objects and messages aka methods.
Looks like it’s easy with #2, but what about #3? It says every object has it’s own memory (which can be revealed only by sending and received messages, by the way). In example before object’s memory contains, probably, last and first names of a person. But what’s not said here – can incoming message mutate internal state of an object? Is following code valid?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
FP doesn’t give another answer to ‘internal state mutability’ question because FP doesn’t speak in terms of objects and messages, but if it would we would say ‘no, objects are not allowed to change it’s state once the are created’. If you haven’t heard about that before and can bring only one item out of this article – let it be this one:
Functional programming is a programming using immutable data structures and immutable references
This is not accurate and not full definition of FP – but I consider this as most important part of a paradigm. FP is an art of restricting yourself to immutable things – and all other stuff comes from that. Let’s see, if we can still write meaningful things without mutability.
Smallest building block in FP is a pure function. There’s a lot of smart words around that – referential transparrency or morphism, but in simple words pure function is a plain old programming function, which has 2 properties:
- It’s result depends only on input parameters
- It’s only job is to calculate it’s result, it does nothing else – in other words, it doesn’t have side effects.
I’m sure you uderstood already what pure function is, but let’s have some examples:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
Let’s have few extra words about last case. As I said before, we can say it’s sending a message ‘length’ to object “Some string”, but on the other side, there’s nothing wrong in looking on it as a function length with one parameter “Some string”. A fact that strings are immutable in Java helps in that paradigm shift a lot.
1 2 3
Let’s add this to our definitions:
Functional programming is a programming using only immutable references/data structures and pure functions
Ok, forbidden ourselfves to use mutations, we forgot about objects and messages and we are using functions instead – for what? Why on Earth would I use only a subset of possible ways to express a logic of a program? Why should I restrict myself to writing only pure functions?
Think about the following:
Only thing that interests us with pure function is it’s result. In fact, we can replace call to pure function with it’s result value – and it won’t change what our program does. By the way, this property is called referential transparency.
But there’s a lot of options for you to get the result value. You can calculate result during compilation if you know function arguments in compile time. Or in another thread. Or in another process. Or at another machine. Or you can not calculate the value before it’s really needed. Or you can cache the value and return result from cache for same function arguments.
Oh, by the way, did I mention multithreading? Usually it’s almost physical pain to debug a mutlithreaded program build in conventional way. FP changes that – doesn’t matter which thread executed the specific function or if it executed at all. In fact, there are prototypes of automatic program paralellization. Think about that – program which knows nothing about multithreading at all, can be run in mutlithreading environment.
Ok, but what if we need mutations? What do we do to change last name of existing user?
Well, we don’t. Instead of destructive updates – we copy to new instance every time we need to change something:
1 2 3 4 5 6
That looks like a huge waste of resources – when we are changing things a lot, we’re going to have a lot of copies in our memory. Anyway, fact that all our data structures are immutable, opens a door for some optimizations which can be done by compiler or runtime, for example you can reuse structures or it’s parts in different places. Because things are immutable, we can not fear one part of our program impacting other by implicitly changing state of a shared structure.
With that whole class of concurrency problems just go away, so using immutable structures is a good idea not only in FP, but in OOP as well – Joshua Bloch recommends “Minimize mutability” in his book Effective Java
So, we have immutable structures and pure functions – and those are building blocks in FP. If you restrict yourself to this things – you’re doing FP, if you relax a restriction and doing some other things – you’re outside of FP land.
Also notice we’ve lost notice of objects and messages – we don’t need them anymore. As I said before, it’s just a matter of syntax – do we put first argument first or after function name:
In FP we don’t mix data and behavior inside of our objects, instead we have them split in different places – our data structures are skinny and contain only data and our functions work with every argument they are provided with – if it conform some preconditions, of course. Note, we haven’t talked about types yet – but we’re going to do that in next parts of a series.