Most programmers use SQL on a daily basis and we don't hear arguments that it should be procedural to be inline with our other languages.
(Not familiar with databases at all)
As I re-read it, read this article, and pondered some more, I'm revising my view a bit, and beginning to think of "declarative" as something like probability. This is debatable, but I tend to agree with the idea of probability as a measure of knowledge of a given agent, and all probabilities must be understood in the context of some agent for whom those are the correct probabilities, as opposed to being free-standing numbers.
Similarly, declarative can be seen as relative to the programmer. Haskell code that looks like
map (+1) . filter isEven . map (*2)
may be declarative to one programmer while writing it, who doesn't care about the details, yet be essentially imperative to someone who, say, is tasked with optimizing that, and cares about exactly what the compiler does with that code and how. It's not a characteristic of the code, but the programmer's relationship to the code, which may even change over time.From this perspective, most things that proudly wear the label "declarative" can be seen as over-forcing you to be ignorant about their implementation details by making this unnecessarily opaque, for the purpose of wearing that label. Still not a tradeoff I like, vs. the same tech except transparent.
What's nice about this is that it removes the "programmer" from the equation and instead augments language with a bouquet of interpretations. Another Haskell interpretation, e.g., is the static nature of its typing relation.
This is a good way of "understanding monads" as well. They're an algebraic structure which captures just enough to let us talk about a variety of sequential/operational semantic choices for our syntax. At the end of the day, though, they're just data and we can imbue them with all of the semantic notions we enjoy via the interpreter pattern. This is even more emphasized with the "Free Monad" pattern which lets the structure of the monad be very, very close to the syntactic notion.
Implicitly, I'm invoking the idea that a programmer is looking at a particular runtime.
I feel like I have to put that in, or the whole distinction between declarative and imperative completely collapses anyhow. "X.sort()" conceptually simply invokes sorting behavior, possibly with a certain set of guarantees, but in practice, it's very unusual for that to be running so abstractly that the programmer can not penetrate down to relevant runtime details. And when that does happen, generally forces are created that start pushing all the switchable runtimes towards bug-for-bug compatibility, e.g. the web browser's Javascript runtime.
It's not a "bad" thing that it collapses in that case, it just does, that is, consider this the mathematical "collapses" rather than the architectural. You have to have a certain amount of specificity in my opinion or there is no reasonable way to discuss "declarative" vs. "imperative".
I will mention two things that give some clarity about the potential of declarative and intelligent techniques:
1/ Z3[1] (satisfiability modulo theories solver) where you declare what you want and it contains many strategies and previous knowledge to achieve the goals.
2/ Gregory Chaitin[2] saying (can't find the source, probably was a lecture I attended) something like that artificial intelligence is an engineering problem, may be we need a lot of ugly pieces to make it work instead of elegant algorithms.
So I think nobody is working really hard at a higher level to look at the problems we have and find a declarative way to solve them. This solution probably will require a lot of field research and ugly disparate modules.
A good example of this would be to favor a templating language to render your HTML where possible, rather than building your HTML directly from your code using string concatenation.
One of the biggest motivation for them is mathematics. All mathematics is written declaration on paper, and mathematics accomplishes so much, so we should follow that model.
They fail to realize that math on paper is only half the story. The other half is the 'computation' going on in the mind of the mathematician. And even mathematicians haven't reduced it into declaration.
Bottomline: Hybrid approach is superior to 'pure-computational' or 'pure-declarative'.
What you're saying amounts to basically an instruction not a relation or declaration in the programming sense of the word.
<div visible="after:5pm">
hello world
</div>Of course, that lets you specify the execution time, but unless you have a system consuming the format that is aware of the additional semantics beyond the base HTML semantics, specifying that won't do anything.
You could say main=printf("Hello World"), which declares that your program is equivalent to the action of printing "Hello World".
You could also say that main=sleep(1), which declares that your program is equivent to the program sleep(1).
You can also say that main=sleep(1) >> printf("Hello World"), which says that your program is equivent to the program that sleeps for a second, then prints "Hello World".
You can even create syntactic sugar around the concatenation operator, so it looks like you are programming in an imperative language.
If the concatenation operator happens to be over-loadable, you can do a lot of neat stuff with it. Even if it isn't, you can define common control flow operations (such as for loops) at the language level, which means that you can just as easily define new control flow operations that the language designers didn't think of.
int main() { sleep(1); printf("Hello World"); return 0; }
And then you can say "pure functions can be evaluated in any order". Maybe impure functions can be suffixed by a !. print "Hello World"
with suitable syntax tweaks, is imperative, functional (that code works in Haskell), declarative, and logical (Prolog has a print). Or, more accurately, is simply too small to be usefully discussed in this context. You have to pick something larger to talk about.Consider a website. An entire website can be modeled as a function that takes headers, URL and request body as parameters and returns headers and body as the response.
You can use the same principle to model almost anything. You take real inputs as inputs and output instructions for imperative side-effect to a minimalist agent of some sort.