"We say the operation is declarative if, whenever called with the same arguments, it returns the same results independent of any other computation state."
That's the use of the term 'declarative programming' by the functional programming community. There are some other uses of it.
Usually in computer science 'declarative programming' means: the problem is described and way to the solution is determined from the problem description. A declarative program describes 'what' and not 'how'. The detailed control flow is not described.
This is a declarative program - it describes being an ancestor means (the parent of a person or an ancestor of the parent of a person). The program does not specify the steps to find a ancestor given a descendant or a descendant given an ancestor. Yet we can do such queries thanks to Prolog's resolution procedure:
?- ancestor(steve,mark).
true
findall(A,ancestor(A,mark),L).
L = [john, steve].
?- findall(D,ancestor(steve,D),L).
L = [john, mark].
Of course, as the sibling poster points out, it's a spectrum. Even Prolog has procedural aspects: the ordering of clauses has an effect on execution, as well as the use of cuts, etc. But the definition cited is more a definition for pure functional programming.
Isn't it fairer to say that any non-trivial Prolog program has significant procedural aspects? Yes, you can construct small examples that are purely declarative, and therefore map nicely to predicate calculus, but I found that eventually as programs grew in complexity you ended up using Prolog as yet another procedural language with a few isolated bits of interesting behaviour.
I suspect that's why there was a brief phase where people were keen on embedding Prolog engines into more conventional platforms as specialized "inference engines" rather than trying to do everything in Prolog.
Only if you get lazy. It is certainly possible to write in a mostly declarative fashion, though loading of initial conditions and saving results don't map well. I write non-trivial declarative stuff (I hesitate to use the word programs) in CNF‡, and that pseudo-language simply lacks every sort of traditional control structure. (I've done Conway's GoL so I guess turing-level computation could be implemented.)
Prolog does make it very easy to fall off the declarative wagon, but the imperative parts should only be used sparingly as glue code.
My recollections (they are a bit vague as it was ~20 years ago) was that you could write the "core" of your solution (I was looking at simulations of things like power stations) in nice declarative Prolog - but then, inevitably, your glue/interface code grows in complexity faster than your "core" so that you end up with that dominating and I didn't think Prolog was great for that at all.
I think I eventually gave up on it entirely and ended up writing something in Lisp that took systems of ODEs and wrote standalone C++ models.
It isn't just about being lazy. I'd argue that the foreach that exists in a couple of Prologs is not declarative (despite being called logical loops etc.) but I still use it because I prefer that over repeating myself.
Repeated clauses as OR gets pretty cumbersome once you work with bigger codebases because it sort of violates DRY. If you change/refactor something...suddenly you have to wade through a bunch of clauses. I've rewritten quite a few of these by falling back on imperative code.
That's the definition of "referentially transparent", not declarative. I don't think the FP community has or attempts a shared definition of "declarative". It's just sort of a feeling and, as such, has all the associated woo woo properties.
For a counterpoint from a (contentious) expert, try http://existentialtype.wordpress.com/2013/07/18/what-if-anyt.... Here, Harper lays out 8 definitions of "declarative" which might have force. You don't have to agree that this list is comprehensive, but I know that I've personally heard arguments using most of those "definitions".
In http://existentialtype.wordpress.com/2013/07/22/there-is-suc... Harper argues a particular definition of "declarative" near to his heart. The critical could argue that his earlier list was aimed at nothing more than exposing this definition. Harper's idea is that declarative languages are ones with "mathematical variables" instead of just "computer science-y assignables or slots".
I don't care whether or not that's your definition of declarative as well, but I think variable v. assignable is a very nice, hard distinction between languages.
The difference to me is maybe not as formal, though if I had to pick one I'd pick your definition: declarative is when variables are like mathematical variables, and not like turing-machine memory cells.
To me the difference is in the level of abstraction.
In a non-declarative language, one way to reverse a list is to traverse it, remembering the last item, and change the pointer of the current item to point to the remembered item (if there's no remembered item, the current item is the head of the list, and we make it point to the list terminator). So we have to say exactly how to build the value we're interested in, the reversed list.
Whereas in a declarative language, I simply give a definition of what a reversed list is, without saying how to go about doing it. In fact the computer is free to come up with any way it wants to do this, and I can define a reversed list as being the fold of construction over that list.
Prelude> foldl (flip (:)) [] [1,2,3,4]
[4,3,2,1]
Which does not force me, the programmer, to use any mutable memory cells; in other words this operation is loosely defined enough that it could be "run" both destructively and immutably. The fact that the function declaration does not specify the implementation is what I usually mean by "declarative".
I think there's generally a UI/UX notion of "declarative", the "declarative feel". There's also that whole list of technical definitions. The mismatch is one of category as much as of definition.
For instance, I would analyze your foldl example as being driven by the fact that foldl has a denotation above its implementation. But, as Harper notes, all languages have a denotational semantics if we choose to recognize them and it's difficult to say what it means for a denotational semantics ti be "better" than another in any technical sense.
So what is declarative?
In my mind, it should really only be a UX term. I think technical definitions are debated because of the category mismatch alluded to earlier. I think notions like "equational semantics", "denotational semantics", "referentially transparent", and "variable" are the right technical terminology.
I've seen "declarative" languages that included if statements (explicit dynamic behavior!) still passed off as declarative. Some even add sequencing, and what not. However, its ok because they aren't part of the language core, just escape hatches on expressiveness :)
"Declarative" always exists in a spectrum: one's specification is another's implementation. It used to be that Fortran was "declarative" because you no longer had to write machine code and schedule instructions by hand! In truth, it is about how many, not just the kind, details can be omitted. E.g. the list order element is probably important, and if HTML couldn't guarantee that this order would be preserved at run-time, there would be some big problems.
> "Declarative" always exists in a spectrum: one's specification is another's implementation.
I'll go further: statelessness and applicativity obviously have an intimate and important relationship with declarativity ("what rather than how") (just as non-Turing-equivalence does), but they're not the same, and trying to simply define the latter as the former is an annoying PR wheeze that spreads obfuscation.
> It used to be that Fortran was "declarative" because you no longer had to write machine code and schedule instructions by hand!
Maybe, but even at that time, pure mathematics was still more declarative than Fortran, so it's not a relative term.
> In truth, it is about how many, not just the kind, details can be omitted.
I think it's about the kind of details that can be omitted. If I can omit implementation details (how to execute my code on a given machine) from my function declaration, then that is a declarative function.
Again, an implementation is just a more detailed specification. I can say "make me a cake", or I could provide a high level theory on cake baking so my cake gets made, or a detailed recipe, or I can describe all the movements needed exactly. Which one is declarative?
There are many levels in describing what one wants, that there is somehow a magical sharp line where it becomes "how" is not reasonable.
> That's the use of the term 'declarative programming' by the functional programming community. There are some other uses of it.
I came here just to say this. This article repeats an annoyingly religious argument about "declarative programming". It's so dogmatic and skewed a definition that it seems to have excluded the canonical example of declarative programming, prolog. Which, for any serious program, relies heavily on cuts and non-referentially transparent I/O.
"When used in Windows Workflow Foundation contexts, XAML is used to describe potentially long-running declarative logic, such as those created by process modeling tools and rules systems."
That's the use of the term 'declarative programming' by the functional programming community. There are some other uses of it.
Usually in computer science 'declarative programming' means: the problem is described and way to the solution is determined from the problem description. A declarative program describes 'what' and not 'how'. The detailed control flow is not described.
• specify static properties of problems
* solutions are computed
* no explicit dynamic behaviour
see also:
http://en.wikipedia.org/wiki/Declarative_programming