Fantastic Functions from Functional Programming
You should know these functions, and get started with Functional Programming.
What is Functional Programming
Functional programming involves writing code that does not change state. The primary reason for doing so is so that successive calls to a function will yield the same result. You can write functional code in any language that supports first-class functions, but there are some languages, like Haskell, which do not allow you to change state. In fact, you’re not supposed to make any side effects (like printing out text) at all — which sounds like it could be completely useless.
Functional programming allows coding with fewer potentials for bugs because each component is completely isolated. Also, using recursion and first-class functions allows for simple proofs of correctness which typically mirror the structure of the code.
1. Pure Function
(Straight from heaven, your friend to clean code)
A Pure function is a function that always returns the same value when passed with the same arguments and has no side effects like mutating some global variables and IO. A pure function can only access what you pass it.
An Impure function contaminates any function that calls it. Ugh! 😫
Some examples of pure functions: list.size(), string.strlen() where if you pass the same argument, you get the same output every single time.
Some examples of impure functions are print(), random(), time(). Printf() even though will return you the same value for the same argument but still, it has a side effect which is IO hence its not a pure function.
If you use GCC (The GNU Compiler Collection (GCC) is a compiler system produced by the GNU Project supporting various programming languages) you can mark functions as “Pure” and it will help you improve performance of the program as compiler applies “Loop Optimizations” and “Subexpression Eliminations” to your pure functions.
for (len = 0; len < strlen(str); ++len)printf("%c", array(str[len]));
If you have your strlen
the function marked as Pure then the compiler will optimize your program in the generated code like this:
int len = strlen(str);for (i = 0; i < len; ++i)
printf("%c", array((str[i]));
Benefits of Pure Functions
- Pure functions help you write a cleaner code where you don’t use global variables which can lead to unnecessary bugs.
- Helps you write a declarative program, describing how inputs relate to outputs and you can see a clear communication between functions.
- Improves testability and debugging, as every function is modular and can be reproduced in isolation.
- Simplifies Concurrency, you can distribute the input values over a number of threads, do your operations and collect the results.
- Memoization for Improving Performance — A result once calculated for a pure function can be cached and reused instead of calling that function again. Hence being lazy and efficient!
2. Functions as a First-Class Citizen
In the world of programming, First-Class citizenship means being able to do what everyone else can do. The given “first-class citizen” function should be able to
- Be assigned to a variable
let fn = function doSomething() {}
- Be passed around as a function argument
callback(fn) {
// Perform something according to the output of fn()
}
- Be returned from a function.
doNetworking(callback : (JSONResponse) -> Unit) {
callback(response)
}// Here callback() is the first-class function which is being returned// This example might be complicated to some, You will get to learn about this in 'Higher Order Function' below.
What is so cool about them?
First-class citizen functions open the doors to all kinds of Programming paradigms and techniques, which also includes Functional Programming. This helps us to pass functions as callbacks to allow us to listen to multiple events without writing much ugly looking code.
Programmers are able to do things using Functional style code for which they had to do a lot of leaps and gymnastics to achieve the same functionality in non-functional paradigm.
Javascript has become very powerful and popular in today’s era of programming because of its functional first-classness. Similarly, Java Lambda expressions help write functional code along with the imperative code which helps Java programmers a big time in reducing a lot of boilerplate ugly code.
You saw above in First-class functions allows us to treat them as values and pass them around. But, first-class functions have some limitations that these functions do not take another function as an input or they cannot return some function or do both. This is where Higher-Order Functions comes in useful.
3. Higher-Order Function
A higher-order function is a function takes another function as input and return a function or does both. Most of the programming languages now support Higher Order functions to make your life easier. Back to the above example:
doNetworking(callback : (JSONResponse) -> Unit) {
callback(response)
}
doNetworking is a higher-order function as it takes a function named callback as input which takes JSONResponse as input parameter and returns void/Unit. doNetworking itself doesn’t return anything here.
Some popular examples of Higher-Order functions are Map(), Filter(), Reduce() , FilterNotNull().
Filter
Filter is a method of arrays. It accepts as an argument a test function which should return a boolean and returns a new array with only the elements for which the test function returned true.
function isEven(x){
return x % 2 === 0;
}const numbers = [12,324,213,4,2,3,45,4234];
const evenNumbers = numbers.filter(isEven);
console.log(evenNumbers);//Outputs even numbers from the list
Filter Not Null
This function return a list of non-nullables items from the list. This is popularly used in Kotlin.
val filtered: Map<String, Any> =
map.filterValues { it != null }.mapValues { it -> it.value as Any }
Map
Map takes a function and applies it to all the elements of an array.
const numbers = [1,2,3,4,5,6,10,20];
const squares = numbers.map((x) => Math.pow(x,2));
console.log(squares);// Here we are using a Lambda Function which just means an anonymous that is taking x as input parameter and returns whatever is mentioned after '=>' i.e. Math.popw(x,2)
Reduce
Reduce is one of the most powerful higher-order functions. It is used for List Transformation.
Reduce takes in a callback function and a starting value, the callback function takes an accumulator as an argument and the value of the current element of the array and returns the accumulator to be used in the next cycle. The value returned from the last call of the callback function is the value returned by reduce.
Multiplying all elements of an arrayconst numbers = [2,3,4,5];
const product = numbers.reduce((acc, x) => acc * x, 1);
console.log(product);//Outputs 120
Reduce here is taking two arguments,
- A callback function which is highlighted in bold above (which is again a Lambda Function)
- The current value of the accumulator. For start, we set it to 1. This accumulates the value as we iterate over the list multiplying the elements.
Some great resources to checkout
- What are first-class functions by LispCast.
- Practical Introduction to Functional Programming by CodingGame.
That is it for Day 3. Hope you got to learn something “fantastic” today! 😉
#100DaysOfCode Series
Day 1:
Day 2:
More to come every day 😎