(This is essentially a repost of something that used to be on my old blog.)
In particular, LiveJournal makes a fantastic case study, since they had their old style system that basically allowed for substituting end-user-chosen color values into developer-written HTML (one HTML file per each of the four views that they offered: main journal, friends page, calendar, and... whatever I’ve forgotten). When they designed a next-generation style system, S2, the templates were code and could produce all of the views from a single file. And of course that file could define functions to share across the views and declare semantic color names instead of “weak accent color #2 foreground”. (Along with other options like “place sidebar on left/right”, IIRC.) S2 also has the interesting property of being non-Turing-complete by design: the only looping construct it offers is over finite lists. Even so, they also have a time limit set so that the server doesn’t melt beyond a certain point when load gets high.
LJ’s S2 is just the end-point of evolution of the realization that templates are code: if you want to display a list of items, or a distinct block with a “Sorry, no results found” message in case the list is empty, these are fundamentally a process driven by the result set into the output language (HTML for S2).
If a template language is strictly declarative, then the template language is no longer self-contained: instead of being able to set data and then have the template interpreter run, the higher level code becomes responsible for inspecting the data for optional/looping parts, and composing the resulting template itself. Responsibilities a template processor would normally take on become implemented in the nearest level of non-template code.
CSS is doing its best to maintain declarative purity, which is why CSS generators like Less and Sass have come about: they give you a stateful, imperative layer above CSS with which to generate CSS. Alternatively, they’re a template language (still non-declarative) that simply results in CSS instead of HTML.
Spreadsheets could be the poster child of declarative languages, but this was also seen as limiting enough to give Excel a macro system, and conditional formatting. The latter was something I wanted at one point in then-OpenOffice.org, but I had to make do with an extra column, styled appropriately, filled with
=IF(stuff, "+OK", "")formulas: this would fill the cell with a plainly visible value whenever stuff was true.
Another common “declarative” language is SQL, except that it is also intimately involved with process. Performance can change drastically depending on whether a conditional can be resolved at
HAVINGtime. In fact, that last one is pretty much useless in real code; specifying “do all this complicated work, and then narrow down the results of that” fails to be efficient even at small scales. The query analyzer does have some freedom to rewrite SQL code into more efficient execution plans, but most RDBMSes offer tools like index and join order hints to give programmers and DBAs more control over the process. In any case, every SQL optimization guide ever explains the effect of SQL in terms of the process the DB engine must go through to satisfy the terms, so that process is constantly leaking out from behind the language.