DEV Community

Cover image for Functional Programming with JS
Mahmoud Hassan
Mahmoud Hassan

Posted on

Functional Programming with JS

Functional programming is a programming paradigm designed to handle pure mathematical functions. This paradigm is totally focused on writing more compounded and pure functions.

Functional programming is a particular kind of declarative programming.

First, you need to know the difference between declarative programming and imperative programming, they are js paradigms or techniques to organize your code.
In imperative programming, we specify the program logic describing the flow control.

let name = "Ali";
let Greeting = "Hi, ";
console.log(Greeting , name);  // Hi,  Ali
Enter fullscreen mode Exit fullscreen mode

In the opposite, declarative programming we specify the program logic without describing the flow control

const Greeting = (name) => {
    console.log('Hi, ',name);
}

Greeting("Ali"); // Hi, Ali
Enter fullscreen mode Exit fullscreen mode

So, as you have noticed, the functional programming focuses on the code being clean, organized, and reused through

  1. Pure Functions: are simple and reusable. They are completely independent of the outside state(global variables), easy to refactor, test and debug. A pure function is a function which given the same input, will always return the same output.
const add = (x,y) => x+y;
add(5,4) // 9
Enter fullscreen mode Exit fullscreen mode

Math.random is a popular example of not pure function.
another example for not pure function:

let count = 0;
const incCount = (value) => count += value;
Enter fullscreen mode Exit fullscreen mode
  1. Higher-Order Functions: they can receive a function as a parameter(callback) and also can return a function, they are very helpful for writing complex functions.
const animals = ["Cat", "Dog", "Elephant",
 "Giraffe", "Lion", "Monkey"];
const zooWithoutCat = animals.filter(animal => animal !== "Cat");
Enter fullscreen mode Exit fullscreen mode

Note ==> Don't Iterate you can use higher-order functions like map, filter, reduce, find...

let numbers = [2, 4, 6];
let numbersX2 = numbers.map(number => number*2); // [ 4, 8, 12 ]
Enter fullscreen mode Exit fullscreen mode
  1. Avoid Mutability: you must avoid changing the data.
let num1 = [1, 2, 3];
let num2 = num1;
Enter fullscreen mode Exit fullscreen mode

any change in num2 affects num1 (mutability), we can fix this problem by using higher-order functions or spread operator.

let num2 = [...num1];
Enter fullscreen mode Exit fullscreen mode
  1. Persistent Data Structures for Efficient Immutability

Think of all data as immutable, never changing.

the problem with immutability is that you need to copy all data for a little change and this can give you efficiency problems, because you will use a lot of space, so What is the solution?
Don't Worry
there are many of js libraries that handle this problem like:

  • Mori
  • Immutable.js
  • Underscore
  • Lodash
  • Ramda they depend on structural sharing idea Image description Note that the yellow squares are shared between 2 variables.

Thanks for your time
you can add me on LinkedIn: Link

Discussion (4)

Collapse
peerreynders profile image
peerreynders • Edited on

In the opposite, declarative programming we specify the program logic without describing the flow control

Looking at Wikipedia we find the following definition:

Declarative programming is often defined as any style of programming that is not imperative.

In my experience that is an incredibly bad definition (and perhaps even incorrect). Defining things entirely in terms what they are not is usually a sign of trouble.

Declarative programming typically lets you focus on describing what you want rather than describing how to get it.

SQL is a good example of declarative programming. This may seem confusing at first because aren't you telling the RDBMS "how to" join and intersect tables to get the data you want? No, that SQL is a description of the data you are interested in — you are not telling the RDBMS engine "how to get" the data — it will figure that out on it's own — but you are communicating what set of data you are interested in.

The reason functional programming is often considered declarative is because in languages like Haskell there is "little emphasis on explicit sequencing" — and sequencing is a big part of "control of flow".

In my opinion the first step to make your JavaScript "less imperative" is to shift focus away from "how things are done" to "what/why things need to be done". The simplest way to accomplish that is to stop relying on inline code and to name most if not all your functions in a way that reflects "what/why things need to be done".

While we all know "naming is hard" one doesn't get better by avoiding it — if you think of a better name later change it.

Seeing the function name explaining "what/why things need to be done" is more "declarative" than leaving the inline code in place which has to be mentally parsed again and again every time somebody reads the code.

But the real big difference between imperative and functional programming is "control of flow" and "transformation of values". Rich Hickey calls this the difference between:

  • Place-Oriented programming
  • Value-Oriented programming

So from that perspective your second code example should have been

const greeting = (name) => `Hi, ${name}`;

console.log(greeting('Ali'));
Enter fullscreen mode Exit fullscreen mode

i.e. greeting is the function that transforms the value 'Ali' to 'Hi, Ali' and that value is then passed to the run time system for display.

Imperative programming relies heavily on statements for flow of control while functional programming relies on expressions and functions for the transformation of values. Both expressions and functions have to produce a value (even if it's undefined) — statements do not.

Now given that out of the box JavaScript is mutable by default and doesn't support persistent data structures I think pursuing functional programming with it is a fool's errand (maybe look at ReScript instead) — though value-oriented programming can be often quite useful. I do believe that JavaScript is function-oriented. The existence of libraries is neither here nor there (you didn't mention immer) but in its core capacity as a browser automation language it should travel light and delegate as much work as possible to the browser's native code.

To enjoy the benefits of functional programming in JavaScript I'd look at the strategies that are employed in Rust — namely:

  • Don't modify what you intend to share.
  • Don't share what you intent to modify.

Unfortunately there is no borrowck in JavaScript to help manage ownership — there's only developer discipline. Controlled mutability in the right places (typically local) is your friend, mindless mutability is the enemy.

Collapse
jonrandy profile image
Jon Randy • Edited on

Your 'adding' example of a pure function is kind of a pure function, but not for the reason you think it is. Your function does not have a return, so is implicitly returning undefined - so, yes, it always returns the same thing given the same inputs - but in this case, that 'same thing' is always undefined.

Another reason that it isn't really 'pure' is that it completely relies on outside state - i.e. console.log - which it has no control over - someone could easily redefine console.log to have different behaviour.

Also, pure functions should try to avoid side effects (modifying state outside of the function) - console.log is clearly a side effect

Collapse
trezeguit profile image
Mahmoud Hassan Author

Thanks a lot for your note, I will rewrite this example.

Collapse
ibrahimkamal profile image
Ibrahim Kamal

eh el gamal da ya hoda