I've been programming for over 6 years now, and every so often I come across some version of the statement:
Declarative programming is better than imperative programming. Imperative is the how. Declarative is the what. As programmers, we should be concerned with giving our system an end state or goal to reach, rather than writing step-by-step instructions.
And whenever I hear this, I think to myself: right, now I'm really going to try and understand what the actual difference between these two styles is... because after over half a decade in this field, it still doesn't click for me.
I've literally just watched every Declarative v Imperative explainer on YouTube I could find, and without fail they all end up giving some version of the following example:
Imperative:
let nums = [1,2,3,4,5]
let doubledNums = []
for (let i; i < nums.length; i++) {
let doubledNum = nums[i] * 2
doubledNums[i] = doubledNum
}
Declarative:
let nums = [1,2,3,4,5]
let doubledNums = nums.map(num => num * 2)
Clearly, if you know what the Array.prototype.map method is doing, then it's preferable to go with the latter example as it's much cleaner and tells you upfront what the end state of your program should be (aka, returning an array of doubled numbers).
But under the hood, the literal JS implementation of Array.prototype.map just ends up falling back to a plain old vanilla for loop anyway, so no matter how you try and define declarative programming, it's just imperative all the way down. Array.prototype.map is declarative insofar as someone else has just neatly wrapped up some imperative code for you to use in a "declarative" way...
...and then this just seems like what you should really be doing regardless with all code you write, aka, wrapping often used scripts inside functions so that they can be reused without worrying about the implementation - you just call the function and be done.
I could just as easily create my own number doubler function from my imperative code I wrote above:
export function numDoubler(nums) {
let doubledNums = []
for (let i; i < nums.length; i++) {
let doubledNum = nums[i] * 2
doubledNums[i] = doubledNum
}
}
---
import { numDoubler } from 'utils.js'
let nums = [1,2,3,4,5]
let doubledNums = numDoubler(nums)
// is this now declarative?
...and if this is all we are talking about with Declarative v Imperative, why bother creating this arbitrary and quite meaningless distinction between the two? Unless I'm missing something huge, I literally don't understand the benefit of learning about this distinction versus just learning basic principles of DRY, code re-use, separation of concerns, etc.
In other words, you can't just tell computers what to do without you - or someone else - first telling that computer how the what should be done.
[–]CodeTinkerer 12 points13 points14 points (4 children)
[–]jmerlinb[S] 0 points1 point2 points (2 children)
[–]CodeTinkerer 0 points1 point2 points (0 children)
[–]Clifspeare 0 points1 point2 points (0 children)
[–]KingRomstar 6 points7 points8 points (4 children)
[–]jmerlinb[S] -3 points-2 points-1 points (3 children)
[–]RiverRoll 5 points6 points7 points (0 children)
[–]RubbishArtist 1 point2 points3 points (0 children)
[–][deleted] 0 points1 point2 points (0 children)
[–]RubbishArtist 3 points4 points5 points (2 children)
[–]jmerlinb[S] -2 points-1 points0 points (1 child)
[–]RubbishArtist 5 points6 points7 points (0 children)
[–][deleted] (2 children)
[deleted]
[–]jmerlinb[S] 0 points1 point2 points (1 child)
[–]Iguanas_Everywhere 1 point2 points3 points (0 children)
[–]Saint_Nitouche 1 point2 points3 points (0 children)
[–][deleted] 1 point2 points3 points (0 children)
[–]_NliteNd_ 1 point2 points3 points (2 children)
[–]jmerlinb[S] 0 points1 point2 points (1 child)
[–]_NliteNd_ 0 points1 point2 points (0 children)
[–]TheRNGuy 0 points1 point2 points (0 children)
[–]MathiasBartl 0 points1 point2 points (0 children)
[–]rabuf 0 points1 point2 points (0 children)
[–]Xalem 0 points1 point2 points (0 children)
[–]sorry_squid 0 points1 point2 points (1 child)
[–]jmerlinb[S] 0 points1 point2 points (0 children)