Functional Programming in Bash
simple ways and means to be more functional in your scripts
What is functional programming?
It is a programming paradigm where programs are written by defining functions or expressions which evaluates into the value corresponding to the argument. Same as what happens in mathematics. The value of the function only depends on the arguments provided.
So we can say that the functions answer the question “what is defined.”
On the other hand in the procedural language this is like steps needed to get to the desired language. This is similar to answering the question: “how to do it. tell me the steps”
On the outside it seems it feels like this should be easy. But in reality this is very hard to implement and reason about.
Its because of the reasoning surrounding the code correctness is harder. Its not enough to look at the code. You must also think of all the cases and take care be extra careful of all the edge cases and take care of them. So the best case scenario becomes that the real functionality of the code is obfuscated by all the edge cases that would need to be handled
Result: Code reading is tougher; Code maintenance is tougher.
So how can we write more functional code?
To do this we need to keep in mind what makes our code more functional.
- No State
As you know all variables in bash by default is global. This greatly hampers code reading. Now to be fair there is the `local` keyword but we all know that no one uses it.
So instead of the following happening where a local assignment can change the value of a global variable.
We will do the following.
2. No re-assignment/minimal assignment.
We can create separate functions and implement the execution order through pipes.
3. Referential transparency
If a program is referentially transparent then we can manipulate its programs as algebraic equations.
4. Lazy evaluation
One of the ways lazy evaluation is achieved is using the eval function although this is not generally approved of. Functions are another great way to achieve lazy programming as the functions are not actually evaluated till they are called.
Nice work using a function to delay evaluation putting the code in a function will introduce lazy evaluation to it
Also lets look into `[[`. This does lazy evaluation `]]`. Simple `[]` is not capable of doing lazy evaluation.
If you come from other functional languages then you must be familiar with the list expressions In bash it is implemented using the following construct.
5. Writing higher order functions
If you don’t need anything fancy like delaying the evaluation of the function name or its arguments, you don’t need eval.
does what you want. You can even pass the function and its arguments this way.
Finally for the more advanced enthusiasts I will urge you to check out the bash-lambda library for more advanced implementations of functional paradigms, like futures, filtering and lambda functions.
References:
http://www.cs.uku.fi/~mnykanen/FOH/lectures1.pdf
http://stackoverflow.com/questions/5672289/bash-pass-a-function-as-parameter
http://unix.stackexchange.com/questions/60688/how-to-defer-variable-expansion
https://lists.gnu.org/archive/html/help-bash/2014-06/msg00013.html