The pendulum between server heavy app and client heavy app. has swung back to the client again for this epoch and single page applications are all the rage. This would have seemed like insanity at the turn of the century but advances in browser technology and a demand for more ambitious applications has led us to the now infamous
SPA. Our programs live a lot longer in the browser than they used to. Gone are the days when we could rely on a browser refresh to reboot the browser code and rebuild clear all our objects from memory.
reactjs has come up with a beautfiul top down, one way data push that can simulate this behaviour by abstracting away that gargantuan side effect known as the DOM into a virtual DOM to diff against the previous state. Reactjs has embraced functional programming and so should you.
Side effects, function Purity and Referential Transparency
Functional programming favours functions that, for a given input, will consistently return the same output. A pure function does not depend on and does not modify the state of variables outside of its scope. When a function performs any other action, apart from calculating its return value, the function is impure. A program or function is said to have side effects if it can produce different outputs given the same input.
A very simple example of a pure function is below:
Referential transparency is the ability to freely replace an expression with its value and not change the behaviour of the program. We can show that the
mult function is both pure and
referentially transparent with the code below:
1 2 3 4 5 6 7 8 9
Replacing the call to
mult with the result does not alter the output of the computation.
Below is an example of a function that relies on a global variable to calculate its output:
1 2 3 4 5 6 7 8 9 10 11 12
We can clearly see that providing the same input each time does not give us the same output each time.
Side effects are functions that rely on the outside OR can be functions that alter the outside world. The ubiquitous
Hello World program is actually a side effect because it alters the state of the output on the screen. A call to
console.log is a side effect. All IO is side effect laden, reading a file from a disk is a side effect because it might throw an exception because the network is unavailable. We therefore cannot guarantee the result of calling the function.
Any function that does not return a value will more than likely have side effects because it is probably mutating some external state.
Immutable Data Structures
In the chaotic realm of the single page application, I find it very reassuring to know that after I have created an object or assigned a value to a variable, it will not be changed by some well meaning code outside of my control. A lot of SPA frameworks use two way data binding to bind objects to DOM elements or other structures. I have also had hellish results with using observation through
Object.observe or some other mechanism of reacting to state changes, I now consider this to be an anti-pattern.
es6 has introduced the
const keyword which is analogous to
final in java, it does not mean that all data structures defined with the
const keyword are immuable but it does mean they cannot be reassigned once they have been assigned. The code sample below will illustrate this:
1 2 3 4 5 6 7 8 9 10 11
If we want full immutability then we can use something like immutable-js or mori. Both libraries provide persistent data structures for your use. The data structures are called persistent because they always presist a previous version of themselves when modified.
Below is an example of
immutable-js that illustrates this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
You can see from the above that we can check equality by value and not reference on
line4 when comparing
Also illustrated is how
map2 returns a reference to
line 7 because no change was made to the underlying hash and on
map1 remains unchanged and a new version of the data structure is returned after changing or adding a new value to part of the data strurcture. I hope you can see how we could use persistent data structures to trivially hookup undo and redo functionality (more on this later).
Imperative programming works by changing programming state to produce answers. Conversely, functional programming produces answers through stateless operations.
This brings us back to function purity, our programs are easier to reason about if we can be sure that given the same input, we get the same output. We want to avoid functions that reference member variables or any thing outside of the functions environment wherever possible.
Back to the Real world
- Are my functions dependant on the context in which they are called, or are they pure and independent?
- Can I write these functions in such a way that I could depend on them always returning the same result for a given input?
- Am I sure that these functions won’t modify anything outside of themselves?
- Pass values as parameters, don’t store state in member variables.
I blogged here here about using a real world example to limit side effects in an emberjs application and here about how you can use persistent data structures in an emberjs application to implement basic undo and redo functionality.
Higher Order Functions
A higher order function is either:
- A function that takes a function as an argument
- A function that returns a function
I am going to concentrate on the latter and I am going to first of all use partial application.
Wikipedia gives the following definition of partial application:
partial application (or partial function application) refers to the process of fixing a number of arguments to a function, producing another function of smaller arity
If we return to our
mult function that I showed in the beginning, we can create a new function
double by using partial application:
1 2 3 4 5
line 3 of the above, I am using the lesser known property of bind that after the first argument where you can specify a context, every parameter after the first will be prepended to the list of parameters when invoking the bound function.
We could rewrite the
double to return a function like this:
1 2 3 4 5 6 7 8 9 10 11
We now have a
makeMultiplier that can create many different types of functions based on
A more practical use of a higher order function is the
maybe function below that can take a function and return a null safe version:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
Here we create a new null save function that is returned from the
maybe function. We can now create other functions from this
maybe function that will handle null values.
Another benefit of higher order functions is to take 2 or more functions and combine them into one. Below is an
and function that will perform a logical and on the output of two functions:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
Further down the rabbit Hole
There are a number libraries that go much further with respect to functional programming:
- Built on top of reactjs
- Top down rendering
- Immutable Data
- Built on top of reactjs
- Written clojurescript
- ClojureScript’s immutable data types
- Inspired by haskell
- Type system
- Bindings for reactjs and angular
- Compiler guarantees no runtime exceptions