Page 1 of 2
Now available as a book from your local Amazon.
The Amazing Parts
- Jem 2 The Inheritance Tax
- Jem 3 Functions Are Objects
- Jem 4 Objects, Functions And this
- Jem 5 Every Object Is An Anonymous Singleton
- Jem 6 Objects Have Value
- Jem 7 Numbers And Other Values
- Jem 8 Truthy And Falsey
- Jem 9 The Comma
- Jem 10 Code As Data
- Jem 11 Lambda Expressions
- Jem 12 Fluent Interfaces
- Jem 13 Hoisting, Scope And Lifetime
- Jem 14 Amazing Async
- Jem 15 The Revealing Constructor Pattern
- Jem 16 Functional And Not Quite Functional
- Jem 17 Immutability
- Jem 18 Functional Approach To Iteration
Extract 1 Functional Iteration
- Jem 19 Metaprogramming - The Proxy
Jem 16 Functional And Not Quite Functional
“Whoever said that pleasure wasn't functional?”
Most programmers who adopt a functional style don't go the whole way and essentially make use of the easy and rewarding parts of the idea. This isn't necessarily a bad thing, but it does leave you open to criticism that you don't really know what functional is - so let’s put that right.
The Essence of Functional Programming
Functional languages try to reduce, or is it enhance, programming languages to mathematical functions. That is, when you use a mathematical function its result never changes - the result of sin(0.3) is always the same - and a function is just a lookup table. Sometimes the lookup table is too big to be stored and in this case the result is returned after being calculated using a procedure - but in theory all mathematical functions can be implemented as lookup tables. Converting a function that produces a result by calculation into one that stores the results in a lookup table is often referred to as memoization.
That is, mathematical functions provide a way to do computation without any dynamic change. A function returns its result and it is the same result for the same input. It is static and stateless.
This isn't so with the procedural programming meaning of functions or procedures. In the programming context, a function is just a procedure that returns a single value as its result. All procedures can be cast as functions by the simple trick of having them return a single, but perhaps complicated structure, containing all their results rolled up into one object. That is, in general, a function can accept and return objects including other functions.
A programming function can produce “side effects“ and state changes, for example:
In this case each time the function is called it returns a new value - it is counting - it is procedural - and this can't be allowed in a functional language. In addition, it changes a global variable and this is a side effect. If another function makes use of the same global then its behavior will have been changed.
A function that gives the same result every time it is called with the same parameters and one that has no side effects is called a pure function. The goal of functional programming is to use nothing but pure functions.
In a functional language the sort of counting described above isn't allowed and variables aren't variable in the sense that once defined they have that value for the duration of the program - they are "bound" to their value. In other words, all objects are immutable. Once created an object cannot be changed.
At this point non-functional programmers generally give up because this is nothing like the way they think. How can there be loops and conditions if variables never change? How can the counting function be implemented in a pure way with immutable objects?
There are two answers to this question. The first is why are you counting at all? If the counting is part of an algorithm that gets you to a solution then don't do it - simply get the solution. That is, if you implement sin(0.3) with an iterative calculation, simply hide the iteration behind the function and return the result. In other words pretend that there is no iteration involved and leave it to hidden non-functional implementations.
The second answer is that there are functional ways of doing the same job, mostly recursion and functional composition. For example, if f(x) is a function which returns x+1 then counting can be implemented as:
and so on...
Notice that in the set of nested functions:
only one variable z is bound to the result, no variables change their values and yet even so there is still an "increment" as you work your way into the brackets.
This is how pure functions can be used to count. In principle the function does something with the count, much as you would in a for loop say. This is, the functional language’s equivalent of the fixed repeat for loop. There are also equivalents of for loops that perform variable numbers of repeat using either functional composition or recursion.
For example, if you want to count down from N to 0 you would use:
Notice that as N is used as a parameter its value isn't changed as a new N comes into existence each time the function is called. Some programmers take to recursion and some don't. Recursion is natural for some problems and less so for others. Notice that this is a pure function, but if you put an ??alert in the body to display the count it has a side effect and is no longer pure.
So the main principles of functional programming are:
First class functions – for function composition and higher order functions.
Pure functions - functions always return the same output for the same input and have no side effects.
Immutable data - data is never changed once created and new data is created in place of mutation.
Recursion is a natural way of avoiding mutating data and provides an alternative to iteration.
How strictly these are obeyed varies a great deal and you can program in a way that is slightly functional, mostly functional or hard line, that is nothing but functional styles. In many cases programmers opt to take the immediate advantages of functional programming by using first class functions, functional composition and higher order functions, but tend to be less concerned about avoiding side effects, allowing mutable data and using recursion.