DEV Community

Cover image for Declarative Programming with JavaScript
Adnan Babakan (he/him)
Adnan Babakan (he/him)

Posted on • Edited on

Declarative Programming with JavaScript

Hey there DEV.to community!

As you know, JavaScript is a pretty vast programming language. Meaning that it doesn't limit you to a specific paradigm, and you can implement almost every famous paradigm and go on with it.

This made me think about how we can go on with the declarative paradigm instead of imperative. In case you don't know what these words mean, here is a simple explanation: Imperative means you tell the compiler what you exactly want to happen, while in declarative paradigm you only specify what you want the result to be.

Declarative style is best followed in functional programming languages while it is pretty fun to follow this style in JavaScript.

Iteration through an array

Perhaps this sample will make it obvious for you what the difference between an imperative and a declarative paradigm is.

Usually what you'd do is to define a for loop as below:

let n = [-9, 87, 72, 452, 32, -9]
for(let i = 0; i < n.length; i++) {
    console.log(n[i])
}
Enter fullscreen mode Exit fullscreen mode

This is called the imperative way. While by using forEach prototype of arrays, it is possible to rewrite this in a declarative way:

let n = [-9, 87, 72, 452, 32, -9]
n.forEach(v => console.log(v))
Enter fullscreen mode Exit fullscreen mode

Both these codes have the same result, but the second one looks cleaner and more readable. Isn't it awesome?

Array mapping

Mapping is the action of applying a specific function to every item inside an array resulting in a new array.

Here is the imperative way:

let n = [-9, 87, 72, 452, 32, -9]
let z = []
let doubleMinusOne = x => (x * 2) - 1
for(let i = 0; i < n.length; i++) {
    z[i] = doubleMinusOne(n[i])
}
Enter fullscreen mode Exit fullscreen mode

Now the z variable holds an array of items doubled and subtracted by one from the n array.

Here is how to do it declaratively:

let n = [-9, 87, 72, 452, 32, -9]
let z = n.map(v => (v * 2) - 1)
Enter fullscreen mode Exit fullscreen mode

Very short and concise!

Array filtering

What if you wanted some items from an array matching a condition? Here is how you'd do it normally in an imperative way:

let n = [-9, 87, 72, 452, 32, -9]
let z = []
let lessThanFifty = v => v < 50
for(let i = 0; i < n.length; i++) {
    lessThanFifty(n[i]) && z.push(n[i])
}
Enter fullscreen mode Exit fullscreen mode

And the code below is the declarative counterpart:

let n = [-9, 87, 72, 452, 32, -9]
let z = n.filter(v => v < 50)
Enter fullscreen mode Exit fullscreen mode

KABOOM!

Reduce

This is the most amazing method ever existed and is very powerful! As the name suggests this method reduces array to a single value.

What if you wanted to have the summation of the numbers inside an array? What you'd probably do is as below:

let n = [-9, 87, 72, 452, 32, -9]
let s = 0
for(let i = 0; i < n.length; i++) {
    s += n[i]
}
Enter fullscreen mode Exit fullscreen mode

Here is the magic of reduce!

let n = [-9, 87, 72, 452, 32, -9]
let s = n.reduce((acc, v) => acc + v)
Enter fullscreen mode Exit fullscreen mode

The first argument of the function that reduce takes is called accumulation (or total) which holds the value of the previous value returned by the function. Each time we are adding the current value (second argument) to the accumulation.

The reduce method is not limited to summation only, and you can do almost everything!

let n = [-9, 87, 72, 452, 32, -9]
let m = n.reduce((acc, v) => acc * v)
Enter fullscreen mode Exit fullscreen mode

Here is another awesome example. Finding the maximum (or minimum) value inside an array is simply possible by a simple algorithm:

let n = [-9, 87, 72, 452, 32, -9]
let maximum = n[0]
for(let i = 1; i < n.length; i++) {
    if(n[i] > maximum) maximum = n[i]
}
Enter fullscreen mode Exit fullscreen mode

Although it is pretty simple, by using the reduce function it is possible to rewrite it in a declarative way which makes it very short (and professional-looking as well xD)!

let n = [-9, 87, 72, 452, 32, -9]
let maximum = n.reduce((max, v) => v > max ? v : max)
let minimum = n.reduce((min, v) => v < min ? v : min)
Enter fullscreen mode Exit fullscreen mode

Given that you have a two-dimensional array and you want to flatten it. Here is the imperative way using a for loop:

let n = [[-9, 87], [72], 452, [32, -9]]
let flatten = []
for(let i = 0; i < n.length; i++) {
    if(Array.isArray(n[i])) flatten = flatten.concat(n[i])
    else flatten.push(n[i])
}
Enter fullscreen mode Exit fullscreen mode

And now again! The power of reduce:

let n = [[-9, 87], [72], 452, [32, -9]]
let flatten = n.reduce((acc, v) => acc.concat(v), [])
Enter fullscreen mode Exit fullscreen mode

The second argument passed to the reduce method (the empty array) is for the reduce method to know the initial value of the accumulation.


Hope you enjoyed this article!

Top comments (2)

Collapse
 
danacoding profile image
DanaCoding

So, can imperative style be called "loose style"; can declarative style be called "functional style"

Collapse
 
bart76 profile image
Bart76

Functional programming is a particular kind of declarative programming paradigm. Functional programming is somewhat more strict than declarative programming in general, I guess. Therefore, not all declarative programming paradigms can be considered to be functional programming paradigms as well.

I would personally avoid the term "loose style", because (afaik) it is not a common term in this context and you would need to explain why you would call it "loose" every time somebody else would be confronted with it. If you would use the term "loose style" in a conversation about programming paradigms with me, I would probably not understand what you mean until you would explicitly clarify it or provide some concrete examples.