Perhaps for the sheer MentalMasturbation, does anybody want to present a clear definition candidate for "declarative"?
I suggest Declarative is essentially simultaneous, idempotent, continuous, reactive along with a few common expressiveness concerns. I'll define these a bit further on, and start with the 10-point score:
So where does HTML (by itself) score? simultaneity: 1/2, idempotence: 0.5/2, expressiveness: 2/2, reactivity 1/2 (both half-points), continuous: 2/2. Total 6.5/10. Moderately declarative.
Definitions of simultaneity, idempotent, continuous, reactive:
simultaneity: Declarations are simultaneous in the sense that declarations are in effect at once. For example, if you state:
The ball is round. The ball is red.A declarative interpretation of these assertions is that the ball is (simultaneously) round and red. There is no risk of a second declaration 'undoing' the first.
A consequence of the simultaneity property is that the order of declarative statements should not matter. This is in stark contrast to imperative statements, where one would see considerable difference between "Open door. Walk through door." and its opposite ordering. The simultaneity of statements actually reduces complexity, since one only needs to consider combinations of statements rather than additionally considering permutations of them.
As a note, this means declarations can be inconsistent. For example:
The ball is round. The ball is flat.Since these declarative statements are simultaneous (both in effect at once) but cannot both be true at once, it results in inconsistency. In contrast, imperative statements would have the latter statement undo the other: The ball is now round. The ball is now red. This would implicitly introduce 'time' because there would implicitly be two different values for 'now'.
One could resolve the inconsistency in a declarative program by any number of means, such as explicit time or contingencies, or weakened declarations with priority or fuzziness. One possible resolution:
The ball is usually round. The ball is flat when the sun is shining upon it.It should be noted that using explicit time (as with TemporalLogic or FunctionalReactiveProgramming) to resolve inconsistencies does allow imperative styles of programming (i.e. one can model stacks and queues and ActorsModel and so on). But by making time explicit, you can add it in small doses where necessary (such as animations) rather than having it permeate every statement by default, and you also separate timing of statements from their syntactic order; the expressions are still concurrent.
How to handle inconsistency is usually a big deal for a declarative language.
idempotent: An identical declaration stated twice has no additional effect.
The ball is round. The ball is round.Idempotence has a lot of nice, entirely practical properties for optimization, especially when combined with concurrency (so interleave doesn't matter). For an example, something like:
(f() + g()) / (f() - g()) let a=f(), b=g() in ((a+b)/(a-b)) // legal optimization if f,g concurrent+idempotentFurther, widespread idempotence is useful for abstractions. I.e. consider the following expression where a,b,c,d are arbitrary subexpressions:
h(b,a+b)*h(c,a+c)*h(d,a+d)Without idempotence, it would be unclear whether we can reduce this. Perhaps evaluating b, c, d twice each has twice the effect? But if idempotence is widespread in the language, then one can reason about and abstract programs more easily, i.e. producing:
let h2(x) = h(x,a+x) in h2(b)*h2(c)*h2(d)It is worth noting that 'pure' programs (without SideEffects) necessarily have the idempotence property, but it is also feasible to build a language where all the SideEffects relevant to abstraction and optimization are idempotent. ConcurrentConstraintProgramming (SideEffect is to add a constraint to the constraint store) and ReactiveDemandProgramming (SideEffect is to demand of an external system) are examples.
continuous: declarations have logical continuity; they are not imperative statements that assert themselves then vanish, nor are they in a loop, asserting periodically. Instead, they maintain continuously over their lifetime. In opposition, a process (even one that is simultaneous and idempotent) may mutate and diverge from the original declaration, possibly even 'return' in a volatile manner. This suggests a language based on declarative statements will need to treat declarations more like data than process, even to the point of maintaining a graph or database of declarations. A corollary is that set of things derived from the initial set of declarations is monotonic within any given logical-instant. Finally, if one ends up creating a lot of short-lived declarations, one might well be GreenSpunning an imperative language; this continuity is an important part of the declarative 'feel'.
reactive: a declaration language moderate expressiveness will be able to declare relationships between variables or other named elements in a system. Since these declarations are continuous, the declared relationships must be maintained over time. For example, if we declared in the past that X equals Y+1, and Y increases, then X must also increase. One could get away with not being reactive by not being expressive enough for it to matter: do not allow elements that change over logical time, or do not support declarations over time.
These properties of declarations are what people refer to when they say "declarative" as more than a technical buzzword. The properties correspond well to systems or styles widely considered declarative today, including LogicProgramming, ConstraintProgramming, ConstraintLogicProgramming, ConcurrentConstraintProgramming, ReactiveProgramming, FunctionalReactiveProgramming.
They are reasonably objective, individually. It's easy to duplicate statements duplicate statements to see whether the output is the same. It's reorder easy to the statements also to see whether they are simultaneous. Continuity and reactivity are a bit tougher to judge, requiring more knowledge and context, but there is no reason to believe they'd be a source of difficulty.
DeclarativeDefinitionDiscussionOne for three or four prior attempts.
See also: DeclarativeProgramming, DeclarativeMetaprogramming, DeclarativeGui, LiberatingConstraint, GrandParadigmUnification, FeatureBuffetModel