Based on http://blog.ninjaferret.co.uk/2015/06/05/Introducing-Functional-Calisthenics.html & http://tomphp.github.io/functional-programming/2015/06/21/functional-calisthenics-in-clojure.html
- Side effects can only occur at the top level
- No mutable state
- Functions should have no more than 2 arguments
- Maximum level of abstraction
- Always use infinite sequences
- No ifs
- No Loops
- No Classes, aside from what's demanded by your language
We want the majority of our code to be pure functions and in order for that to be the case they cannot depend on anything that is impure. This means we should pull the impure functions up to the top level and isolate them as much as possible from the rest of the code. This can include:
- User interaction
- Output to screen
- API calls
As well as creating pure functions, we don't want to mutate state within a function either, e.g. do not change the value of variables once they have been set. This has a negative impact on code readability and any mutable state could potentially result in an unintended consequence.
We should be using restricting the number of arguments that a function can take, a function with a large number of arguments smells of a single responsibility principle violation. Automatic currying doesn't count!
Functions should take and return values at the highest level of abstraction possible, e.g. if List is a special case of Enumerable then the function should take Enumerable.
If you function takes, or returns, a sequence of data then write the function in a way that does not exclude infinite sequences - allow for tail recursion etc.
Avoid using if statements. "if" is just a special case of pattern matching anyway.
Loops are for noobs. Get declarative and/or recursive!
As if you'd want to!