Back in the 1980’s it was very fashionable to talk about “declarative” programming languages. But to my mind there was never a clear definition of a “declarative language”, and hence no way to tell what is declarative and what is not. Lacking any clear meaning, the term came to refer to the arbitrary conflation of functional with logic programming to such an extent that “functional-and-logic-programming” almost became a Germanic thing-in-itself (ding an sich). Later, as the logic programming wave subsided, the term “declarative”, like “object-oriented”, came to be an expression of approval, and then, mercifully, died out.
Or so I had thought. Earlier this week I attended a thriller of an NSF-sponsored workshop on high-level programming models for parallelism, where I was surprised by the declarative zombie once again coming to eat our brains. This got me to thinking, again, about whether the term has any useful meaning. For what it’s worth, and perhaps to generate useful debate, here’re some things that I think people mean, and why I don’t think they mean very much.
- “Declarative” means “high-level”. This just seems to replace one vague term by another.
- “Declarative” means “not imperative”. But this flies in the face of reality. Functional languages embrace and encompass imperative programming as a special case, and even Prolog has imperative features, such as assert and retract, that have imperative meaning.
- “Declarative” means “functional”. OK, but then we don’t really need another word.
- “Declarative” means “what, not how”. But every language has an operational semantics that defines how to execute its programs, and you must be aware of that semantics to understand programs written in it. Haskell has a definite evaluation order, just as much as ML has a different one, and even Prolog execution is defined by a clear operational semantics that determines the clause order and that can be influenced by “cut”.
- “Declarative” means “equational”. This does not distinguish anything, because there is a well-defined notion of equivalence for any programming language, namely observational equivalence. Different languages induce different equivalences, of course, but how does one say that one equivalence is “better” than another? At any rate, I know of no stress on equational properties of logic programs, so either logic programs are not “declarative” or “equational reasoning” is not their defining characteristic.
- “Declarative” means “referentially transparent”. The misappropriation of Quine’s terminology only confuses matters. All I’ve been able to make of this is that “referentially transparent” means that beta-equivalence is valid. But beta equivalence is not a property of an arbitrary programming language, nor in any case is it clear why this equivalence is first among equals. In any case why you would decide a priori on what equivalences you want before you even know what it means to run a program?
- “Declarative” means “has a denotation”. This gets closer to the point, I think, because we might well say that a declarative semantics is one that gives meaning to programs as some kind of mapping between some sort of spaces. In other words, it would be a synonym for “denotational semantics”. But every language has a denotational semantics (perhaps by interpretation into a Kripke structure to impose sequencing), so having one does not seem to distinguish a useful class of languages. Moreover, even in the case of purely functional programs, the usual denotational semantics (as continuous maps) is not fully abstract, and the fully abstract semantics (as games) is highly operational. Perhaps a language is declarative in proportion to being able to give it semantics in some “familiar” mathematical setting?
- “Declarative” means “implicitly parallelizable“. This was certainly the sense intended at the NSF meeting, but no two “declarative” languages seemed to have much in common. Charlie Garrod proposes just “implicit”, which is pretty much synonymous with “high level”, and may be the most precise sense there is to the term.
No doubt this list is not exhaustive, but I think it covers many of the most common interpretations. It seems to me that none of them have a clear meaning or distinguish a well-defined class of languages. Which leads me to ask, is there any such thing as a declarative programming language?
[Thanks to the late Steve Gould for inspiring the title of this post.]
[Update: add a remark about semantics, add another candidate meaning.]
[Update: added link to previous post.]