“Declarative” and “imperative” are often used as substitutes for “object-oriented” and “functional”. Conflating “declarative” and “functional” creates confusion and hurts programmers.

Without picking on Nick specifically (since the internet is replete with examples of programmers making the same mistake), this essay on Swift 2’s errors serves as an example. Writers that make this mistake often use the word “imperative” as a thinly-veiled insult against OOP.

The value of declarative code is in describing what you’d like to do, rather than concerning yourself with how to perform the task. Let’s examine one of the standard examples that functional programmers use to explain how imperative and declarative code are different. Imperative code is using a for-loop to iterate over an array and perform some task:

var numbers = [1,2,3,4,5]
var total = 0

for(var i = 0; i < numbers.length; i++) {
  total += numbers[i]
}
console.log(total) //=> 15

On the other hand, the declarative style lets you define how each element in an array should be incorporated, via a block, and the reduce method handles applying that incorporation to each element. We no longer have to concern ourselves with how to merge the values, because reduce handles that for us.

var numbers = [1,2,3,4,5]

var total = numbers.reduce(function(sum, n) {
  return sum + n
});
console.log(total) //=> 15

Without question, this second solution is preferable. And it does have the word function in it. But we should resist calling solutions that use blocks or functions “declarative”, because there’s nuance here. I can write code that’s more imperative than the first solution: a C array where elements in the array are mapped directly onto an unbroken block of memory. Or worse: assembly that reads each element into a register and adds it to a “sum” register.

And I can also write code that’s more declarative than the second solution — a message with no parameters that describes exactly what to do, without saying how to do it:

[numbers sum];  

Now, I’d probably never write a method like this. But it’s certainly more declarative. Now I don’t even care how the numbers are added together, and as a cherry on top, there’s no blocks or functions seen anywhere — just a message. Maybe it’s implemented with reduce under the hood, or maybe there are some optimizations in place, but they’re invisible and uninteresting to me. If you think sum is a weird method for an array, think about something like reverse, which could be implemented in terms of reduce, but normally isn’t.

Imperativity-declarativity is a spectrum, and that spectrum lies on an orthogonal axis to the functional/object-oriented divide. As we build abstractions, we go up on the declarativity scale. That’s what reduce (and its friends) are: great abstractions. Abstractions are awesome. If you can understand some concept in the general case, that catapults your thinking much further than if you just dealt the concept in its specific form. Great abstractions don’t have to be complicated to be useful. An Objective-C implementation of map can be done in 5 lines of code.

It’s easy to write imperative code in both functional and object-oriented languages. However, when writing code in either style, great declarative code and great abstractions help increase the facility we have in our domain.